From 55e9037383df98654870186db13031ab50f27bca Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 7 Oct 2019 10:39:50 +0200 Subject: [PATCH 1/2] Added failing test for #2980. --- .../TreeViewTests.cs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index 6c9f0f4f57..a91b7a0701 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -14,6 +14,7 @@ using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Interactivity; using Avalonia.LogicalTree; +using Avalonia.Styling; using Avalonia.UnitTests; using Xunit; @@ -892,6 +893,46 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(2, GetItem(target, 0, 1, 0).Level); } + [Fact] + public void Auto_Expanding_In_Style_Should_Not_Break_Range_Selection() + { + /// Issue #2980. + using (UnitTestApplication.Start(TestServices.RealStyler)) + { + var target = new DerivedTreeView + { + Template = CreateTreeViewTemplate(), + SelectionMode = SelectionMode.Multiple, + Items = new List + { + new Node { Value = "Root1", }, + new Node { Value = "Root2", }, + }, + }; + + var visualRoot = new TestRoot + { + Styles = + { + new Style(x => x.OfType()) + { + Setters = + { + new Setter(TreeViewItem.IsExpandedProperty, true), + }, + }, + }, + Child = target, + }; + + CreateNodeDataTemplate(target); + ApplyTemplates(target); + + _mouse.Click(GetItem(target, 0)); + _mouse.Click(GetItem(target, 1), modifiers: InputModifiers.Shift); + } + } + private void ApplyTemplates(TreeView tree) { tree.ApplyTemplate(); From 75fdd0d3432a033c0b8c93e8d583754c58a6a2e3 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 7 Oct 2019 10:41:44 +0200 Subject: [PATCH 2/2] Check for empty items in GetContainerInDirection. Don't try to navigate into `TreeViewItem`s with no children: this causes a out-of-range exception. Fixes #2980 --- src/Avalonia.Controls/TreeView.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs index cc47365214..8907137ecb 100644 --- a/src/Avalonia.Controls/TreeView.cs +++ b/src/Avalonia.Controls/TreeView.cs @@ -1,3 +1,4 @@ + // Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. @@ -470,7 +471,7 @@ namespace Avalonia.Controls if (index > 0) { var previous = (TreeViewItem)parentGenerator.ContainerFromIndex(index - 1); - result = previous.IsExpanded ? + result = previous.IsExpanded && previous.ItemCount > 0 ? (TreeViewItem)previous.ItemContainerGenerator.ContainerFromIndex(previous.ItemCount - 1) : previous; } @@ -482,7 +483,7 @@ namespace Avalonia.Controls break; case NavigationDirection.Down: - if (from.IsExpanded && intoChildren) + if (from.IsExpanded && intoChildren && from.ItemCount > 0) { result = (TreeViewItem)from.ItemContainerGenerator.ContainerFromIndex(0); }