diff --git a/src/Avalonia.Controls/Generators/TreeContainerIndex.cs b/src/Avalonia.Controls/Generators/TreeContainerIndex.cs index 24b3fc1f32..0da84008f6 100644 --- a/src/Avalonia.Controls/Generators/TreeContainerIndex.cs +++ b/src/Avalonia.Controls/Generators/TreeContainerIndex.cs @@ -34,7 +34,12 @@ namespace Avalonia.Controls.Generators /// /// Gets the currently materialized containers. /// - public IEnumerable Items => _containerToItem.Keys; + public IEnumerable Containers => _containerToItem.Keys; + + /// + /// Gets the items of currently materialized containers. + /// + public IEnumerable Items => _containerToItem.Values; /// /// Adds an entry to the index. diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index a54bb502c0..a64dbe0546 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -10,6 +10,7 @@ using Avalonia.Collections; using Avalonia.Controls.Generators; using Avalonia.Data; using Avalonia.Input; +using Avalonia.Input.Platform; using Avalonia.Interactivity; using Avalonia.Styling; using Avalonia.VisualTree; @@ -459,6 +460,23 @@ namespace Avalonia.Controls.Primitives } } + protected override void OnKeyDown(KeyEventArgs e) + { + base.OnKeyDown(e); + + if (!e.Handled) + { + var keymap = AvaloniaLocator.Current.GetService(); + bool Match(List gestures) => gestures.Any(g => g.Matches(e)); + + if (this.SelectionMode == SelectionMode.Multiple && Match(keymap.SelectAll)) + { + SynchronizeItems(SelectedItems, Items?.Cast()); + e.Handled = true; + } + } + } + /// /// Moves the selection in the specified direction relative to the current selection. /// diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs index db8de49494..94989254dc 100644 --- a/src/Avalonia.Controls/TreeView.cs +++ b/src/Avalonia.Controls/TreeView.cs @@ -10,6 +10,7 @@ using Avalonia.Collections; using Avalonia.Controls.Generators; using Avalonia.Controls.Primitives; using Avalonia.Input; +using Avalonia.Input.Platform; using Avalonia.Interactivity; using Avalonia.Threading; using Avalonia.VisualTree; @@ -244,7 +245,7 @@ namespace Avalonia.Controls break; case NotifyCollectionChangedAction.Reset: - foreach (IControl container in ItemContainerGenerator.Index.Items) + foreach (IControl container in ItemContainerGenerator.Index.Containers) { MarkContainerSelected(container, false); } @@ -402,6 +403,18 @@ namespace Avalonia.Controls SelectedItem = ElementAt(Items, 0); } } + + if (!e.Handled) + { + var keymap = AvaloniaLocator.Current.GetService(); + bool Match(List gestures) => gestures.Any(g => g.Matches(e)); + + if (this.SelectionMode == SelectionMode.Multiple && Match(keymap.SelectAll)) + { + SelectingItemsControl.SynchronizeItems(SelectedItems, ItemContainerGenerator.Index.Items); + e.Handled = true; + } + } } private TreeViewItem GetContainerInDirection( diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index f65ef7d08e..519872f9f2 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -54,7 +54,7 @@ namespace Avalonia.Controls.UnitTests ApplyTemplates(target); - var items = target.ItemContainerGenerator.Index.Items + var items = target.ItemContainerGenerator.Index.Containers .OfType() .ToList(); @@ -463,11 +463,11 @@ namespace Avalonia.Controls.UnitTests CreateNodeDataTemplate(target); ApplyTemplates(target); - Assert.Equal(5, target.ItemContainerGenerator.Index.Items.Count()); + Assert.Equal(5, target.ItemContainerGenerator.Index.Containers.Count()); tree[0].Children.RemoveAt(1); - Assert.Equal(3, target.ItemContainerGenerator.Index.Items.Count()); + Assert.Equal(3, target.ItemContainerGenerator.Index.Containers.Count()); } [Fact]