From 0449eeb3add2f36a78dbc3fe69148a183615d444 Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Wed, 23 Oct 2024 16:04:40 +0200 Subject: [PATCH 1/4] test: CollectionView enumeration validations --- .../Given_CollectionView.cs | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Data/Given_CollectionView.cs diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Data/Given_CollectionView.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Data/Given_CollectionView.cs new file mode 100644 index 000000000000..7ed33a9d99d9 --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Data/Given_CollectionView.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.Metrics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml; +using Windows.Foundation.Collections; + +namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Data; + +[TestClass] +[RunsOnUIThread] +public class Given_CollectionView +{ + [TestMethod] + public void When_Grouped_With_ItemsPath() + { + var data = new List + { + new("1", "Test 1|1", "Group 1"), + new("2", "Test 2|1", "Group 1"), + new("3", "Test 3|1", "Group 1"), + new("4", "Test 1|2", "Group 2"), + new("5", "Test 2|2", "Group 2"), + new("6", "Test 3|2", "Group 2"), + new("7", "Test 1|3", "Group 3"), + new("8", "Test 2|3", "Group 3"), + new("9", "Test 3|3", "Group 3"), + }; + + var groupedItems = from item in data + group item by item.GroupName into g + select new { GroupName = g.Key, Items = g.ToList() }; + + var cvs = new CollectionViewSource(); + cvs.IsSourceGrouped = true; + cvs.ItemsPath = new PropertyPath("Items"); + cvs.Source = groupedItems.ToList(); + + var type = GetItemType(cvs.View); + Assert.AreEqual(typeof(GroupItemDto), type); + } + + [TestMethod] + public void When_Grouped_Get_Count() + { + var data = new List + { + new("1", "Test 1|1", "Group 1"), + new("2", "Test 2|1", "Group 1"), + new("3", "Test 3|1", "Group 1"), + new("4", "Test 1|2", "Group 2"), + new("5", "Test 2|2", "Group 2"), + new("6", "Test 3|2", "Group 2"), + new("7", "Test 1|3", "Group 3"), + new("8", "Test 2|3", "Group 3"), + new("9", "Test 3|3", "Group 3"), + }; + + var groupedItems = from item in data + group item by item.GroupName into g + select new { GroupName = g.Key, Items = g.ToList() }; + + var cvs = new CollectionViewSource(); + cvs.IsSourceGrouped = true; + cvs.ItemsPath = new PropertyPath("Items"); + cvs.Source = groupedItems.ToList(); + + var count = GetCount(cvs.View); + Assert.AreEqual(9, count); + } + + private int GetCount(ICollectionView view) + { + int num = 0; + IEnumerable dataSource = view; + if (dataSource != null) + { + IEnumerator enumerator = dataSource.GetEnumerator(); + if (enumerator != null) + { + while (enumerator.MoveNext()) + { + num++; + } + } + } + return num; + } + + private Type GetItemType(IEnumerable list) + { + Type type = list.GetType(); + Type type2 = null; + bool flag = false; + if (type2 == null || type2 == typeof(object) || flag) + { + Type type3 = null; + IEnumerator enumerator = list.GetEnumerator(); + type3 = ((!enumerator.MoveNext() || enumerator.Current == null) ? + (from object x in list select x.GetType()).FirstOrDefault() : enumerator.Current.GetType()); + if (type3 != typeof(object)) + { + return type3; + } + } + if (flag) + { + return null; + } + return type2; + } + + private record GroupItemDto(string Number, string Name, string GroupName); +} From f4fe4f0f82b708d038020bce88dbfde7f1dbdbd8 Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Wed, 23 Oct 2024 16:09:39 +0200 Subject: [PATCH 2/4] fix: Grouped CollectionView enumeration --- src/Uno.UI/UI/Xaml/Data/CollectionView.cs | 27 +++++-------------- .../UI/Xaml/Data/CollectionViewSource.cs | 2 +- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/Uno.UI/UI/Xaml/Data/CollectionView.cs b/src/Uno.UI/UI/Xaml/Data/CollectionView.cs index 44bda1834b41..7308aa24d189 100644 --- a/src/Uno.UI/UI/Xaml/Data/CollectionView.cs +++ b/src/Uno.UI/UI/Xaml/Data/CollectionView.cs @@ -172,16 +172,6 @@ public int Count public event VectorChangedEventHandler VectorChanged; //TODO: this should be raised if underlying source implements INotifyCollectionChanged #pragma warning restore 67 // Unused member - public IEnumerator GetEnumerator() - { - // In Windows if CollectionView is from a CollectionViewSource marked grouped, it enumerates the flattened list of objects - if (_isGrouped) - { - return (_collection as IEnumerable> ?? Enumerable.Empty>()).SelectMany(g => g).GetEnumerator(); - } - return (_collection as IEnumerable)?.GetEnumerator(); - } - public IAsyncOperation LoadMoreItemsAsync(uint count) { throw new NotSupportedException(); @@ -260,23 +250,18 @@ void ICollection.CopyTo(object[] array, int arrayIndex) _collection?.ToObjectArray().CopyTo(array, arrayIndex); } - IEnumerator IEnumerable.GetEnumerator() - { - var enumerator = (this as IEnumerable).GetEnumerator(); - while (enumerator.MoveNext()) - { - yield return enumerator.Current; - } - } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() + public IEnumerator GetEnumerator() { // In Windows if CollectionView is from a CollectionViewSource marked grouped, it enumerates the flattened list of objects if (_isGrouped) { - return (_collection as IEnumerable ?? Enumerable.Empty()).SelectManyUntyped(g => g).GetEnumerator(); + return CollectionGroups.OfType().SelectMany(c => c.GroupItems).GetEnumerator(); } - return (_collection as IEnumerable).GetEnumerator(); + return (_collection as IEnumerable)?.GetEnumerator(); } public int IndexOf(object item) => _collection.IndexOf(item); diff --git a/src/Uno.UI/UI/Xaml/Data/CollectionViewSource.cs b/src/Uno.UI/UI/Xaml/Data/CollectionViewSource.cs index d181113a2fe3..acf534207026 100644 --- a/src/Uno.UI/UI/Xaml/Data/CollectionViewSource.cs +++ b/src/Uno.UI/UI/Xaml/Data/CollectionViewSource.cs @@ -62,7 +62,7 @@ public ICollectionView View private set => SetValue(ViewProperty, value); } - public global::Microsoft.UI.Xaml.PropertyPath ItemsPath + public PropertyPath ItemsPath { get => (PropertyPath)this.GetValue(ItemsPathProperty); set => this.SetValue(ItemsPathProperty, value); From ca94c046c12a5b1a67776b2bf4283c3d539ba47f Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Wed, 23 Oct 2024 17:59:07 +0200 Subject: [PATCH 3/4] chore: Adjust typing --- src/Uno.UI/UI/Xaml/Data/CollectionView.cs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Uno.UI/UI/Xaml/Data/CollectionView.cs b/src/Uno.UI/UI/Xaml/Data/CollectionView.cs index 7308aa24d189..88bdebbb703d 100644 --- a/src/Uno.UI/UI/Xaml/Data/CollectionView.cs +++ b/src/Uno.UI/UI/Xaml/Data/CollectionView.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; -using System.Text; using Uno; using Uno.Extensions; using Uno.Extensions.Specialized; @@ -250,9 +249,24 @@ void ICollection.CopyTo(object[] array, int arrayIndex) _collection?.ToObjectArray().CopyTo(array, arrayIndex); } - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() + { + var enumerator = (this as IEnumerable).GetEnumerator(); + while (enumerator.MoveNext()) + { + yield return enumerator.Current; + } + } - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() + { + // In Windows if CollectionView is from a CollectionViewSource marked grouped, it enumerates the flattened list of objects + if (_isGrouped) + { + return CollectionGroups.OfType().SelectManyUntyped(c => c.GroupItems).GetEnumerator(); + } + return (_collection as IEnumerable).GetEnumerator(); + } public IEnumerator GetEnumerator() { From 2e2bdb2a49aa3a0835ef7d8d2a553f085329f290 Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Wed, 23 Oct 2024 22:37:32 +0200 Subject: [PATCH 4/4] chore: Adjust wrong assert --- .../ItemsControlTests/Given_ItemsControl.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Uno.UI.Tests/Windows_UI_XAML_Controls/ItemsControlTests/Given_ItemsControl.cs b/src/Uno.UI.Tests/Windows_UI_XAML_Controls/ItemsControlTests/Given_ItemsControl.cs index 93f84817768d..4d8fe7d5243f 100644 --- a/src/Uno.UI.Tests/Windows_UI_XAML_Controls/ItemsControlTests/Given_ItemsControl.cs +++ b/src/Uno.UI.Tests/Windows_UI_XAML_Controls/ItemsControlTests/Given_ItemsControl.cs @@ -311,9 +311,7 @@ public void When_GroupedCollectionViewSource() SUT.ItemsSource = cvs; - // This behavior is not the UWP one, this assertion - // is present to freeze the behavior. - Assert.AreEqual(0, count); + Assert.AreEqual(11, count); } #endif