From 2e0259266247c873e04b7d2409c8b96dcea086b1 Mon Sep 17 00:00:00 2001 From: Ramez Ragaa Date: Wed, 27 Sep 2023 12:50:40 +0300 Subject: [PATCH] feat(listview): add support for ListView.IsMultiSelectCheckBoxEnabled --- .../Given_ListViewBase.cs | 148 ++++++++++++++++++ .../Windows.UI.Xaml.Controls/ListViewBase.cs | 22 --- .../ListViewBase/ListViewBase.Properties.cs | 25 ++- .../Controls/ListViewBase/ListViewBase.cs | 2 +- .../Xaml/Controls/Primitives/SelectorItem.cs | 4 +- 5 files changed, 175 insertions(+), 26 deletions(-) diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_ListViewBase.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_ListViewBase.cs index bf02559be898..094eab9263ec 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_ListViewBase.cs +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_ListViewBase.cs @@ -645,6 +645,154 @@ public async Task NoItemSelectedSingle() Assert.AreEqual(list.SelectedIndex, -1); } + [TestMethod] + [RunsOnUIThread] + public async Task When_SingleSelection_IsMultiSelectCheckBoxEnabled() + { + var singleList = new ListView + { + SelectionMode = ListViewSelectionMode.Single, + Items = + { + new ListViewItem + { + Content = "child 1" + } + } + }; + + var multipleList = new ListView + { + SelectionMode = ListViewSelectionMode.Multiple, + Items = + { + new ListViewItem + { + Content = "child 1" + } + } + }; + + var extendedList = new ListView + { + SelectionMode = ListViewSelectionMode.Extended, + Items = + { + new ListViewItem + { + Content = "child 1" + } + } + }; + + var singleList2 = new ListView + { + SelectionMode = ListViewSelectionMode.Single, + IsMultiSelectCheckBoxEnabled = true, + Items = + { + new ListViewItem + { + Content = "child 1" + } + } + }; + + var multipleList2 = new ListView + { + SelectionMode = ListViewSelectionMode.Multiple, + IsMultiSelectCheckBoxEnabled = true, + Items = + { + new ListViewItem + { + Content = "child 1" + } + } + }; + + var extendedList2 = new ListView + { + SelectionMode = ListViewSelectionMode.Extended, + IsMultiSelectCheckBoxEnabled = true, + Items = + { + new ListViewItem + { + Content = "child 1" + } + } + }; + + var singleList3 = new ListView + { + SelectionMode = ListViewSelectionMode.Single, + IsMultiSelectCheckBoxEnabled = false, + Items = + { + new ListViewItem + { + Content = "child 1" + } + } + }; + + var multipleList3 = new ListView + { + SelectionMode = ListViewSelectionMode.Multiple, + IsMultiSelectCheckBoxEnabled = false, + Items = + { + new ListViewItem + { + Content = "child 1" + } + } + }; + + var extendedList3 = new ListView + { + SelectionMode = ListViewSelectionMode.Extended, + IsMultiSelectCheckBoxEnabled = false, + Items = + { + new ListViewItem + { + Content = "child 1" + } + } + }; + + var sp = new StackPanel + { + Children = + { + singleList, + multipleList, + extendedList, + singleList2, + multipleList2, + extendedList2, + singleList3, + multipleList3, + extendedList3 + } + }; + + WindowHelper.WindowContent = sp; + await WindowHelper.WaitForIdle(); + + Assert.AreEqual(Visibility.Collapsed, ((Border)singleList.FindName("MultiSelectSquare")).Visibility); + Assert.AreEqual(Visibility.Visible, ((Border)multipleList.FindName("MultiSelectSquare")).Visibility); + Assert.AreEqual(Visibility.Collapsed, ((Border)extendedList.FindName("MultiSelectSquare")).Visibility); + Assert.AreEqual(Visibility.Collapsed, ((Border)singleList2.FindName("MultiSelectSquare")).Visibility); + Assert.AreEqual(Visibility.Visible, ((Border)multipleList2.FindName("MultiSelectSquare")).Visibility); + Assert.AreEqual(Visibility.Collapsed, ((Border)extendedList2.FindName("MultiSelectSquare")).Visibility); + Assert.AreEqual(Visibility.Collapsed, ((Border)singleList3.FindName("MultiSelectSquare")).Visibility); + Assert.AreEqual(Visibility.Collapsed, ((Border)multipleList3.FindName("MultiSelectSquare")).Visibility); + Assert.AreEqual(Visibility.Collapsed, ((Border)extendedList3.FindName("MultiSelectSquare")).Visibility); + } + #if HAS_UNO [TestMethod] [RunsOnUIThread] diff --git a/src/Uno.UI/Generated/3.0.0.0/Windows.UI.Xaml.Controls/ListViewBase.cs b/src/Uno.UI/Generated/3.0.0.0/Windows.UI.Xaml.Controls/ListViewBase.cs index 30dca3ded028..d8a9203f390a 100644 --- a/src/Uno.UI/Generated/3.0.0.0/Windows.UI.Xaml.Controls/ListViewBase.cs +++ b/src/Uno.UI/Generated/3.0.0.0/Windows.UI.Xaml.Controls/ListViewBase.cs @@ -90,20 +90,6 @@ public bool ShowsScrollingPlaceholders } } #endif -#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__ - [global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")] - public bool IsMultiSelectCheckBoxEnabled - { - get - { - return (bool)this.GetValue(IsMultiSelectCheckBoxEnabledProperty); - } - set - { - this.SetValue(IsMultiSelectCheckBoxEnabledProperty, value); - } - } -#endif #if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__ [global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")] public global::System.Collections.Generic.IReadOnlyList SelectedRanges @@ -231,14 +217,6 @@ public bool IsActiveView nameof(ReorderMode), typeof(global::Windows.UI.Xaml.Controls.ListViewReorderMode), typeof(global::Windows.UI.Xaml.Controls.ListViewBase), new Windows.UI.Xaml.FrameworkPropertyMetadata(default(global::Windows.UI.Xaml.Controls.ListViewReorderMode))); -#endif -#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__ - [global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")] - public static global::Windows.UI.Xaml.DependencyProperty IsMultiSelectCheckBoxEnabledProperty { get; } = - Windows.UI.Xaml.DependencyProperty.Register( - nameof(IsMultiSelectCheckBoxEnabled), typeof(bool), - typeof(global::Windows.UI.Xaml.Controls.ListViewBase), - new Windows.UI.Xaml.FrameworkPropertyMetadata(default(bool))); #endif // Skipping already declared property SingleSelectionFollowsFocusProperty // Skipping already declared method Windows.UI.Xaml.Controls.ListViewBase.ListViewBase() diff --git a/src/Uno.UI/UI/Xaml/Controls/ListViewBase/ListViewBase.Properties.cs b/src/Uno.UI/UI/Xaml/Controls/ListViewBase/ListViewBase.Properties.cs index e4573735f8c1..6999a6afcf08 100644 --- a/src/Uno.UI/UI/Xaml/Controls/ListViewBase/ListViewBase.Properties.cs +++ b/src/Uno.UI/UI/Xaml/Controls/ListViewBase/ListViewBase.Properties.cs @@ -1,4 +1,7 @@ -using Windows.UI.Xaml; +using System.Linq; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls.Primitives; +using NotImplementedException = System.NotImplementedException; namespace Windows.UI.Xaml.Controls; @@ -22,4 +25,24 @@ public bool SingleSelectionFollowsFocus typeof(bool), typeof(ListViewBase), new FrameworkPropertyMetadata(true)); + + public bool IsMultiSelectCheckBoxEnabled + { + get => (bool)GetValue(IsMultiSelectCheckBoxEnabledProperty); + set => SetValue(IsMultiSelectCheckBoxEnabledProperty, value); + } + + public static DependencyProperty IsMultiSelectCheckBoxEnabledProperty { get; } = + DependencyProperty.Register( + nameof(IsMultiSelectCheckBoxEnabled), typeof(bool), + typeof(ListViewBase), + new FrameworkPropertyMetadata(true, (o, args) => ((ListViewBase)o).OnIsMultiSelectCheckBoxEnabledPropertyChanged(args))); + + private void OnIsMultiSelectCheckBoxEnabledPropertyChanged(DependencyPropertyChangedEventArgs args) + { + foreach (var item in GetItemsPanelChildren().OfType()) + { + ApplyMultiSelectState(item); + } + } } diff --git a/src/Uno.UI/UI/Xaml/Controls/ListViewBase/ListViewBase.cs b/src/Uno.UI/UI/Xaml/Controls/ListViewBase/ListViewBase.cs index d2bb3f1da519..9f00cb3b4134 100644 --- a/src/Uno.UI/UI/Xaml/Controls/ListViewBase/ListViewBase.cs +++ b/src/Uno.UI/UI/Xaml/Controls/ListViewBase/ListViewBase.cs @@ -1095,7 +1095,7 @@ internal override void ContainerClearedForItem(object item, SelectorItem itemCon /// internal void ApplyMultiSelectState(SelectorItem selectorItem) { - selectorItem.ApplyMultiSelectState(IsSelectionMultiple); + selectorItem.ApplyMultiSelectState(SelectionMode == ListViewSelectionMode.Multiple); } /// diff --git a/src/Uno.UI/UI/Xaml/Controls/Primitives/SelectorItem.cs b/src/Uno.UI/UI/Xaml/Controls/Primitives/SelectorItem.cs index b31b68d300f8..7391bfc1af4a 100644 --- a/src/Uno.UI/UI/Xaml/Controls/Primitives/SelectorItem.cs +++ b/src/Uno.UI/UI/Xaml/Controls/Primitives/SelectorItem.cs @@ -108,7 +108,7 @@ private protected override void OnIsEnabledChanged(IsEnabledChangedEventArgs e) /// internal void ApplyMultiSelectState(bool isSelectionMultiple) { - if (isSelectionMultiple) + if (isSelectionMultiple && Selector is not ListViewBase { IsMultiSelectCheckBoxEnabled: false }) { // We can safely always go to multiselect state VisualStateManager.GoToState(this, "MultiSelectEnabled", useTransitions: true); @@ -285,7 +285,7 @@ private protected override void OnLoaded() UpdateCommonStates(); if (Selector is ListView lv) { - ApplyMultiSelectState(lv.IsSelectionMultiple); + ApplyMultiSelectState(lv.SelectionMode == ListViewSelectionMode.Multiple); } // TODO: This may need to be adjusted later when we remove the Visual State mixins.