From abc36922be8204a15ba361636769fcf048b73a60 Mon Sep 17 00:00:00 2001 From: xiaoy312 Date: Wed, 27 Nov 2024 16:13:39 -0500 Subject: [PATCH] fix(chipgroup): initial selection --- .../Controls/Chips/ChipGroup.cs | 23 +++++++++++++++--- .../Controls/TabBar/TabBarListPanel.cs | 24 ++++++++++--------- .../Extensions/ItemsControlExtensions.cs | 8 ------- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/Uno.Toolkit.UI/Controls/Chips/ChipGroup.cs b/src/Uno.Toolkit.UI/Controls/Chips/ChipGroup.cs index 761b5ef71..84f022f59 100644 --- a/src/Uno.Toolkit.UI/Controls/Chips/ChipGroup.cs +++ b/src/Uno.Toolkit.UI/Controls/Chips/ChipGroup.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Uno.UI.Extensions; + #if IS_WINUI using Microsoft.UI.Xaml; @@ -18,7 +20,6 @@ namespace Uno.Toolkit.UI { public partial class ChipGroup : ItemsControl { - private bool _isLoaded; private bool _isSynchronizingSelection; public ChipGroup() @@ -31,11 +32,26 @@ public ChipGroup() protected override void OnApplyTemplate() { base.OnApplyTemplate(); + + // workaround for #1287 ItemsPanelRoot resolution timing related issue + var presenter = + this.GetTemplateRoot() as ItemsPresenter ?? + this.GetFirstDescendant(); + if (presenter is { }) + { + presenter.Loaded += OnItemsPresenterLoaded; + } } private void OnLoaded(object sender, RoutedEventArgs e) { - _isLoaded = true; + SynchronizeInitialSelection(); + EnforceSelectionMode(); + ApplyIconTemplate(null, IconTemplate); + } + + private void OnItemsPresenterLoaded(object sender, RoutedEventArgs e) + { SynchronizeInitialSelection(); EnforceSelectionMode(); ApplyIconTemplate(null, IconTemplate); @@ -58,6 +74,7 @@ private void OnSelectionMemberPathChanged(DependencyPropertyChangedEventArgs e) private void ApplyIconTemplate(DataTemplate? oldTemplate, DataTemplate? newTemplate) { + if (!IsReady) return; if (oldTemplate == newTemplate) return; foreach (var container in this.GetItemContainers()) @@ -403,7 +420,7 @@ bool ShouldClearSelection(Chip container) } } - private bool IsReady => _isLoaded && HasItems && HasContainers; + private bool IsReady => IsLoaded && HasItems && HasContainers; private bool HasItems => this.GetItems().OfType().Any(); diff --git a/src/Uno.Toolkit.UI/Controls/TabBar/TabBarListPanel.cs b/src/Uno.Toolkit.UI/Controls/TabBar/TabBarListPanel.cs index 1cf455530..ada679ee7 100644 --- a/src/Uno.Toolkit.UI/Controls/TabBar/TabBarListPanel.cs +++ b/src/Uno.Toolkit.UI/Controls/TabBar/TabBarListPanel.cs @@ -17,18 +17,20 @@ namespace Uno.Toolkit.UI { public partial class TabBarListPanel : Panel { - #region Orientation - public Orientation Orientation - { - get { return (Orientation)GetValue(OrientationProperty); } - set { SetValue(OrientationProperty, value); } - } + #region DependencyProperty: Orientation public static DependencyProperty OrientationProperty { get; } = DependencyProperty.Register( nameof(Orientation), typeof(Orientation), typeof(TabBarListPanel), - new PropertyMetadata(Orientation.Horizontal, (s, e) => ((TabBarListPanel)s).OnPropertyChanged(e))); + new PropertyMetadata(default(Orientation), OnOrientationChanged)); + + public Orientation Orientation + { + get => (Orientation)GetValue(OrientationProperty); + set => SetValue(OrientationProperty, value); + } + #endregion public TabBarListPanel() @@ -44,11 +46,11 @@ private void OnLoaded(object sender, RoutedEventArgs e) owner?.OnItemsPanelConnected(this); } - private void OnPropertyChanged(DependencyPropertyChangedEventArgs args) + private static void OnOrientationChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { - if (args.Property == OrientationProperty) + if (sender is TabBar owner) { - InvalidateMeasure(); + owner.InvalidateMeasure(); } } @@ -147,6 +149,6 @@ protected override Size ArrangeOverride(Size finalSize) return finalSize; } - private bool IsVisible(UIElement x) => x.Visibility == Visibility.Visible; + private static bool IsVisible(UIElement x) => x.Visibility == Visibility.Visible; } } diff --git a/src/Uno.Toolkit.UI/Extensions/ItemsControlExtensions.cs b/src/Uno.Toolkit.UI/Extensions/ItemsControlExtensions.cs index 2d3e67280..5a206833b 100644 --- a/src/Uno.Toolkit.UI/Extensions/ItemsControlExtensions.cs +++ b/src/Uno.Toolkit.UI/Extensions/ItemsControlExtensions.cs @@ -56,14 +56,6 @@ item as T ?? /// An empty enumerable will returned if the and the containers have not been materialized. public static IEnumerable GetItemContainers(this ItemsControl itemsControl) => itemsControl.ItemsPanelRoot?.Children.OfType() ?? - // #1281 workaround: ItemsPanelRoot would not be resolved until ItemsPanel is loaded, - // which will be the case between the ItemsControl::Loaded and ItemsPanel::Loaded. - // This is normally not a problem, as the container is typically created after that with ItemsSource. - // However, for xaml-defined items, this could cause a problem with initial selection synchronization, - // which happens on ItemsControl::Loaded. For this case, we will resort to using ItemsControl::Items. - (itemsControl.ItemsSource is null && itemsControl.Items is { } - ? itemsControl.Items.OfType() - : null) ?? Enumerable.Empty(); ///