From 35cbb6982a41fb26bd6c5624efa0c8da80f54528 Mon Sep 17 00:00:00 2001 From: David Oliver Date: Thu, 27 May 2021 05:53:10 -0400 Subject: [PATCH] fix(treeview): Fix error when items of last nested item are cleared --- .../Given_TreeView.cs | 120 ++++++++++++++++++ .../TestsResources.xaml | 9 ++ .../Controls/TreeView/TreeViewViewModel.cs | 4 +- 3 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_TreeView.cs diff --git a/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_TreeView.cs b/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_TreeView.cs new file mode 100644 index 000000000000..953ac5f33ff4 --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_TreeView.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Private.Infrastructure; +using Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls.ListViewPages; +#if NETFX_CORE +using Uno.UI.Extensions; +#elif __IOS__ +using UIKit; +#elif __MACOS__ +using AppKit; +#else +using Uno.UI; +#endif +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using static Private.Infrastructure.TestServices; +using Windows.Foundation; +using Windows.UI; +using Windows.UI.Xaml.Media; +using FluentAssertions; +using FluentAssertions.Execution; +using Uno.Extensions; +using Uno.UI.RuntimeTests.Helpers; +using System.ComponentModel; +using Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls; + +namespace Uno.UI.RuntimeTests.Tests.Microsoft_UI_Xaml_Controls +{ + [TestClass] + [RunsOnUIThread] + public partial class Given_TreeView + { + private ResourceDictionary _testsResources; + + private DataTemplate TreeViewItemTemplate => _testsResources["TreeViewItemTemplate"] as DataTemplate; + + [TestInitialize] + public void Init() + { + _testsResources = new TestsResources(); + } + + [TestMethod] + public async Task When_Sublist_Of_Last_Item_Cleared() + { + var initial_Depth_0 = 0; + var initial_Depth_1 = 64; + var initial_Depth_2 = 96; + + var treeView = new Microsoft.UI.Xaml.Controls.TreeView(); + treeView.ItemTemplate = TreeViewItemTemplate; + var testViewModelItems = Enumerable.Range(0, 2).Select(_ => Get_Depth_0_Item()).ToArray(); + treeView.ItemsSource = testViewModelItems; + WindowHelper.WindowContent = treeView; + + await WindowHelper.WaitForLoaded(treeView); + + await WindowHelper.WaitForNonNull(() => treeView.ContainerFromItem(testViewModelItems.Last().Items.First().Items.Last())); + + var currentItem = testViewModelItems.First().Items.Last().Items.First(); + + Assert.IsNotNull(treeView.ContainerFromItem(currentItem)); + + testViewModelItems.First().Items.Last().Items.Clear(); + + await WindowHelper.WaitFor(() => treeView.ContainerFromItem(currentItem) == null); + + TestViewModelItem Get_Depth_0_Item() => new TestViewModelItem + { + Label = $"Item {++initial_Depth_0}", + Items = + { + Get_Depth_1_Item(), + Get_Depth_1_Item(), + Get_Depth_1_Item(), + } + }; + + TestViewModelItem Get_Depth_1_Item() => new TestViewModelItem + { + Label = $"Subitem {(char)(++initial_Depth_1)}", + Items = + { + Get_Depth_2_Item(), + Get_Depth_2_Item(), + } + }; + TestViewModelItem Get_Depth_2_Item() => new TestViewModelItem { Label = $"Subitem {(char)(++initial_Depth_2)}" }; + } + + public class TestViewModelItem : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + public bool IsExpanded { get; set; } = true; + + public ObservableCollection Items { get; } = new ObservableCollection(); + + public string Label + { + get { return _label; } + set + { + if (_label != value) + { + _label = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Label))); + } + } + } + string _label; + } + } +} diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/TestsResources.xaml b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/TestsResources.xaml index c1ea52a0c863..9f5c50ab2322 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/TestsResources.xaml +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/TestsResources.xaml @@ -2,6 +2,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls" + xmlns:mux="using:Microsoft.UI.Xaml.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> @@ -167,4 +168,12 @@ + + + + diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/TreeView/TreeViewViewModel.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/TreeView/TreeViewViewModel.cs index d733c188e4ed..cd8895e8252c 100644 --- a/src/Uno.UI/Microsoft/UI/Xaml/Controls/TreeView/TreeViewViewModel.cs +++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/TreeView/TreeViewViewModel.cs @@ -471,7 +471,7 @@ private int IndexOfNextSibling(TreeViewNode childNode) bool isLastRelativeChild = true; while (parentNode != null && isLastRelativeChild) { - int relativeIndex = parentNode.Children.IndexOf(childNode); + int relativeIndex = parentNode.Children.IndexOf(child); if (parentNode.Children.Count - 1 != relativeIndex) { isLastRelativeChild = false; @@ -485,7 +485,7 @@ private int IndexOfNextSibling(TreeViewNode childNode) if (parentNode != null) { - int siblingIndex = parentNode.Children.IndexOf(childNode); + int siblingIndex = parentNode.Children.IndexOf(child); var siblingNode = parentNode.Children[siblingIndex + 1]; IndexOfNode(siblingNode, out stopIndex); }