From 4e4c1918ab6dc7cf9b4979dd5b4dde0fc8afd364 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 1 Jul 2019 22:00:19 +0200 Subject: [PATCH] Added failing test for #2660. And a passing test too. Also added some useful methods to `TreeView` to help with this. --- src/Avalonia.Controls/TreeView.cs | 44 +++++++++++- .../TreeViewTests.cs | 67 ++++++++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs index 888f4a2013..e186f08561 100644 --- a/src/Avalonia.Controls/TreeView.cs +++ b/src/Avalonia.Controls/TreeView.cs @@ -164,6 +164,48 @@ namespace Avalonia.Controls } } + /// + /// Expands the specified all descendent s. + /// + /// The item to expand. + public void ExpandSubTree(TreeViewItem item) + { + item.IsExpanded = true; + + var panel = item.Presenter.Panel; + + if (panel != null) + { + foreach (var child in panel.Children) + { + if (child is TreeViewItem treeViewItem) + { + ExpandSubTree(treeViewItem); + } + } + } + } + + /// + /// Selects all items in the . + /// + /// + /// Note that this method only selects nodes currently visible due to their parent nodes + /// being expanded: it does not expand nodes. + /// + public void SelectAll() + { + SynchronizeItems(SelectedItems, ItemContainerGenerator.Index.Items); + } + + /// + /// Deselects all items in the . + /// + public void UnselectAll() + { + SelectedItems.Clear(); + } + /// /// Subscribes to the CollectionChanged event, if any. /// @@ -409,7 +451,7 @@ namespace Avalonia.Controls if (this.SelectionMode == SelectionMode.Multiple && Match(keymap.SelectAll)) { - SynchronizeItems(SelectedItems, ItemContainerGenerator.Index.Items); + SelectAll(); e.Handled = true; } } diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index b66d6ed11c..8defb353b3 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -11,6 +11,7 @@ using Avalonia.Data; using Avalonia.Data.Core; using Avalonia.Input; using Avalonia.Input.Platform; +using Avalonia.Interactivity; using Avalonia.LogicalTree; using Avalonia.UnitTests; using Xunit; @@ -740,6 +741,71 @@ namespace Avalonia.Controls.UnitTests } } + [Fact] + public void Right_Click_On_SelectedItem_Should_Not_Clear_Existing_Selection() + { + var tree = CreateTestTreeData(); + var target = new TreeView + { + Template = CreateTreeViewTemplate(), + Items = tree, + ItemTemplate = new FuncDataTemplate(x => new TextBlock { Width = 20, Height = 10 }), + SelectionMode = SelectionMode.Multiple, + }; + + var visualRoot = new TestRoot(); + visualRoot.Child = target; + + CreateNodeDataTemplate(target); + ApplyTemplates(target); + target.ExpandSubTree((TreeViewItem)target.Presenter.Panel.Children[0]); + target.SelectAll(); + + AssertChildrenSelected(target, tree[0]); + Assert.Equal(5, target.SelectedItems.Count); + + _mouse.Click((Interactive)target.Presenter.Panel.Children[0], MouseButton.Right); + + Assert.Equal(5, target.SelectedItems.Count); + } + + [Fact] + public void Right_Click_On_UnselectedItem_Should_Clear_Existing_Selection() + { + var tree = CreateTestTreeData(); + var target = new TreeView + { + Template = CreateTreeViewTemplate(), + Items = tree, + ItemTemplate = new FuncDataTemplate(x => new TextBlock { Width = 20, Height = 10 }), + SelectionMode = SelectionMode.Multiple, + }; + + var visualRoot = new TestRoot(); + visualRoot.Child = target; + + CreateNodeDataTemplate(target); + ApplyTemplates(target); + target.ExpandSubTree((TreeViewItem)target.Presenter.Panel.Children[0]); + + var rootNode = tree[0]; + var to = rootNode.Children[0]; + var then = rootNode.Children[1]; + + var fromContainer = (TreeViewItem)target.ItemContainerGenerator.Index.ContainerFromItem(rootNode); + var toContainer = (TreeViewItem)target.ItemContainerGenerator.Index.ContainerFromItem(to); + var thenContainer = (TreeViewItem)target.ItemContainerGenerator.Index.ContainerFromItem(then); + + ClickContainer(fromContainer, InputModifiers.None); + ClickContainer(toContainer, InputModifiers.Shift); + + Assert.Equal(2, target.SelectedItems.Count); + + _mouse.Click(thenContainer, MouseButton.Right); + + Assert.Equal(1, target.SelectedItems.Count); + } + private void ApplyTemplates(TreeView tree) { tree.ApplyTemplate(); @@ -874,7 +940,6 @@ namespace Avalonia.Controls.UnitTests } } - private class Node : NotifyingBase { private IAvaloniaList _children;