diff --git a/src/Avalonia.Controls/Generators/TreeContainerIndex.cs b/src/Avalonia.Controls/Generators/TreeContainerIndex.cs index 24b3fc1f32b..c831b7985c7 100644 --- a/src/Avalonia.Controls/Generators/TreeContainerIndex.cs +++ b/src/Avalonia.Controls/Generators/TreeContainerIndex.cs @@ -34,7 +34,12 @@ public class TreeContainerIndex /// /// Gets the currently materialized containers. /// - public IEnumerable Items => _containerToItem.Keys; + public IEnumerable Containers => _containerToItem.Keys; + + /// + /// Gets the items of currently materialized containers. + /// + public IEnumerable Objects => _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 a54bb502c07..a64dbe0546c 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -10,6 +10,7 @@ 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 @@ protected override void OnDataContextEndUpdate() } } + 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 db8de494947..8236c119835 100644 --- a/src/Avalonia.Controls/TreeView.cs +++ b/src/Avalonia.Controls/TreeView.cs @@ -10,6 +10,7 @@ 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 @@ private void SelectedItemsCollectionChanged(object sender, NotifyCollectionChang 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 @@ protected override void OnKeyDown(KeyEventArgs e) 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.Objects); + e.Handled = true; + } + } } private TreeViewItem GetContainerInDirection( diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index f65ef7d08e5..519872f9f28 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -54,7 +54,7 @@ public void Items_Should_Be_Created_Using_ItemTemplate_If_Present() ApplyTemplates(target); - var items = target.ItemContainerGenerator.Index.Items + var items = target.ItemContainerGenerator.Index.Containers .OfType() .ToList(); @@ -463,11 +463,11 @@ public void Removing_Item_Should_Remove_Itself_And_Children_From_Index() 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]