From e9cde299bb282db2ea99a7c6e14d9b43f83b2a35 Mon Sep 17 00:00:00 2001 From: Jeffrey Ye Date: Sat, 25 Aug 2018 15:34:52 -0700 Subject: [PATCH] #1802 add SelectedItemChanged event to TreeView --- .../SelectedItemChangedEventArgs.cs | 36 +++++++++++++++++++ src/Avalonia.Controls/TreeView.cs | 27 ++++++++++++++ .../TreeViewTests.cs | 32 +++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 src/Avalonia.Controls/SelectedItemChangedEventArgs.cs diff --git a/src/Avalonia.Controls/SelectedItemChangedEventArgs.cs b/src/Avalonia.Controls/SelectedItemChangedEventArgs.cs new file mode 100644 index 0000000000..6fb8a2d313 --- /dev/null +++ b/src/Avalonia.Controls/SelectedItemChangedEventArgs.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using Avalonia; +using Avalonia.Interactivity; + +namespace Avalonia.Controls +{ + /// + /// Provides data for the event. + /// + public class SelectedItemChangedEventArgs : RoutedEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The event being raised. + /// The items added to the selection. + /// The items removed from the selection. + public SelectedItemChangedEventArgs(RoutedEvent routedEvent, object newItem, object oldItem) + : base(routedEvent) + { + NewItem = newItem; + OldItem = oldItem; + } + + /// + /// Gets the items that were added to the selection. + /// + public object NewItem { get; } + + /// + /// Gets the items that were removed from the selection. + /// + public object OldItem { get; } + } +} diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs index 2e1c011685..50b45cbb9a 100644 --- a/src/Avalonia.Controls/TreeView.cs +++ b/src/Avalonia.Controls/TreeView.cs @@ -32,6 +32,14 @@ namespace Avalonia.Controls o => o.SelectedItem, (o, v) => o.SelectedItem = v); + /// + /// Defines the event. + /// + public static readonly RoutedEvent SelectedItemChangedEvent = + RoutedEvent.Register( + "SelectedItemChanged", + RoutingStrategies.Bubble); + private object _selectedItem; /// @@ -42,6 +50,15 @@ namespace Avalonia.Controls // HACK: Needed or SelectedItem property will not be found in Release build. } + /// + /// Occurs when the control's selection changes. + /// + public event EventHandler SelectedItemChanged + { + add { AddHandler(SelectedItemChangedEvent, value); } + remove { RemoveHandler(SelectedItemChangedEvent, value); } + } + /// /// Gets the for the tree view. /// @@ -75,6 +92,7 @@ namespace Avalonia.Controls MarkContainerSelected(container, false); } + var oldItem = _selectedItem; SetAndRaise(SelectedItemProperty, ref _selectedItem, value); if (_selectedItem != null) @@ -87,6 +105,15 @@ namespace Avalonia.Controls container.BringIntoView(); } } + + if (oldItem != _selectedItem) + { + var changed = new SelectedItemChangedEventArgs( + SelectedItemChangedEvent, + _selectedItem, + oldItem); + RaiseEvent(changed); + } } } diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index c49c343a45..8295409f7e 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -166,6 +166,38 @@ namespace Avalonia.Controls.UnitTests Assert.True(container.IsSelected); } + + [Fact] + public void Setting_SelectedItem_Should_Raise_SelectedItemChanged_Event() + { + var tree = CreateTestTreeData(); + var target = new TreeView + { + Template = CreateTreeViewTemplate(), + Items = tree, + }; + + var visualRoot = new TestRoot(); + visualRoot.Child = target; + + CreateNodeDataTemplate(target); + ApplyTemplates(target); + + var item = tree[0].Children[1].Children[0]; + + var called = false; + target.SelectedItemChanged += (s, e) => + { + Assert.Null(e.OldItem); + Assert.Same(item, e.NewItem); + called = true; + }; + + target.SelectedItem = item; + Assert.True(called); + } + + [Fact] public void LogicalChildren_Should_Be_Set() {