From 44bb9ba470aeffc642b9b64004d9c224164d95dc Mon Sep 17 00:00:00 2001 From: Kevin B Date: Mon, 30 Oct 2023 23:22:54 -0700 Subject: [PATCH] New API on TreeListView to retrieve parent item (#3355) Fixing binding error on attached property --- .../TreeListViewItemsCollectionTests.cs | 52 +++++++++++++++++++ .../Internal/TreeListViewItemsCollection.cs | 15 ++++++ .../MaterialDesignTheme.TreeListView.xaml | 2 +- MaterialDesignThemes.Wpf/TreeListView.cs | 12 +++++ MaterialDesignThemes.Wpf/TreeListViewItem.cs | 6 --- 5 files changed, 80 insertions(+), 7 deletions(-) diff --git a/MaterialDesignThemes.Wpf.Tests/Internal/TreeListViewItemsCollectionTests.cs b/MaterialDesignThemes.Wpf.Tests/Internal/TreeListViewItemsCollectionTests.cs index 21c64cae3c..ba28ba6034 100644 --- a/MaterialDesignThemes.Wpf.Tests/Internal/TreeListViewItemsCollectionTests.cs +++ b/MaterialDesignThemes.Wpf.Tests/Internal/TreeListViewItemsCollectionTests.cs @@ -591,6 +591,58 @@ public void Replace_TopLevelItem_IsReplaced(int indexToReplace) Assert.Equal(expectedExpanded, treeListViewItemsCollection.GetAllIsExpanded()); } + [Theory] + [InlineData(-1)] + [InlineData(3)] + public void GetParent_WithInvalidIndex_ThrowsOutOfRangeException(int index) + { + //Arrange + ObservableCollection boundCollection = new() { "0", "1", "2" }; + TreeListViewItemsCollection treeListViewItemsCollection = new(boundCollection); + + //Act/Assert + var ex = Assert.Throws(() => treeListViewItemsCollection.GetParent(index)); + Assert.Equal("index", ex.ParamName); + } + + [Fact] + public void GetParent_WithNestedItem_ReturnsParent() + { + //Arrange + ObservableCollection boundCollection = new() { "0", "1", "2" }; + TreeListViewItemsCollection treeListViewItemsCollection = new(boundCollection); + treeListViewItemsCollection.InsertWithLevel(2, "1_0", 1); + treeListViewItemsCollection.InsertWithLevel(3, "1_1", 1); + treeListViewItemsCollection.InsertWithLevel(4, "1_2", 1); + treeListViewItemsCollection.InsertWithLevel(5, "1_2_0", 2); + treeListViewItemsCollection.InsertWithLevel(6, "1_2_1", 2); + treeListViewItemsCollection.InsertWithLevel(7, "1_2_2", 2); + + /* + * 0. 0 + * 1. 1 + * 2. 1_0 + * 3. 1_1 + * 4. 1_2 + * 5. 1_2_0 + * 6. 1_2_1 + * 7. 1_2_2 + * 8. 2 + */ + + + //Act/Assert + Assert.Null(treeListViewItemsCollection.GetParent(0)); + Assert.Null(treeListViewItemsCollection.GetParent(1)); + Assert.Equal("1", treeListViewItemsCollection.GetParent(2)); + Assert.Equal("1", treeListViewItemsCollection.GetParent(3)); + Assert.Equal("1", treeListViewItemsCollection.GetParent(4)); + Assert.Equal("1_2", treeListViewItemsCollection.GetParent(5)); + Assert.Equal("1_2", treeListViewItemsCollection.GetParent(6)); + Assert.Equal("1_2", treeListViewItemsCollection.GetParent(7)); + Assert.Null(treeListViewItemsCollection.GetParent(8)); + } + private class TestableCollection : ObservableCollection { private int _blockCollectionChanges; diff --git a/MaterialDesignThemes.Wpf/Internal/TreeListViewItemsCollection.cs b/MaterialDesignThemes.Wpf/Internal/TreeListViewItemsCollection.cs index 2680e13a15..7836c4af1e 100644 --- a/MaterialDesignThemes.Wpf/Internal/TreeListViewItemsCollection.cs +++ b/MaterialDesignThemes.Wpf/Internal/TreeListViewItemsCollection.cs @@ -82,6 +82,21 @@ public void InsertWithLevel(int index, T item, int level) } } + public object? GetParent(int index) + { + if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException(nameof(index)); + int level = ItemLevels[index]; + if (level == 0) return null; + for (int i = index - 1; i >= 0; i--) + { + if (ItemLevels[i] == level - 1) + { + return this[i]; + } + } + return null; + } + protected override void RemoveItem(int index) { int priorNonRootLevelItems = GetPriorNonRootLevelItemsCount(index); diff --git a/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.TreeListView.xaml b/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.TreeListView.xaml index 9f9c50564d..dba286f8f2 100644 --- a/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.TreeListView.xaml +++ b/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.TreeListView.xaml @@ -326,7 +326,7 @@ - + diff --git a/MaterialDesignThemes.Wpf/TreeListView.cs b/MaterialDesignThemes.Wpf/TreeListView.cs index 3be54c3274..878afa7af9 100644 --- a/MaterialDesignThemes.Wpf/TreeListView.cs +++ b/MaterialDesignThemes.Wpf/TreeListView.cs @@ -202,6 +202,18 @@ static int GetChildrenAndGrandChildrenCountOfPriorSiblings(TreeListViewItemsColl } } + public object? GetParent(object? item) + { + if (InternalItemsSource is { } itemSource && + ItemContainerGenerator.ContainerFromItem(item) is { } container && + ItemContainerGenerator.IndexFromContainer(container) is var index && + index >= 0) + { + return itemSource.GetParent(index); + } + return null; + } + private List GetExpandedChildrenAndGrandChildren(object? dataItem) { List expandedChildren = new(); diff --git a/MaterialDesignThemes.Wpf/TreeListViewItem.cs b/MaterialDesignThemes.Wpf/TreeListViewItem.cs index f880658655..e6bc294920 100644 --- a/MaterialDesignThemes.Wpf/TreeListViewItem.cs +++ b/MaterialDesignThemes.Wpf/TreeListViewItem.cs @@ -112,12 +112,6 @@ internal void PrepareTreeListViewItem(object? item, TreeListView treeListView, i } } - protected override void OnContentChanged(object oldContent, object newContent) - => base.OnContentChanged(oldContent, newContent); - - protected override void OnContentTemplateChanged(DataTemplate oldContentTemplate, DataTemplate newContentTemplate) - => base.OnContentTemplateChanged(oldContentTemplate, newContentTemplate); - public override void OnApplyTemplate() { base.OnApplyTemplate();