Browse Source

feat: expose TreeViewItem expansion status to root event. (#16984)

* feat: expose TreeViewItem expansion status to root event.

* feat: use expand/collapse event similar to Expander.

* feat: 1. delete useless event arg 2. move event to TreeViewItem. 3. Fix documentation. 4. Change routing to Bubble|Tunnel as both parent and children may care about this epxanding status.
Dong Bin 1 year ago
parent
commit
a8a8060617
1 changed files with 39 additions and 0 deletions
  1. 39 0
      src/Avalonia.Controls/TreeViewItem.cs

+ 39 - 0
src/Avalonia.Controls/TreeViewItem.cs

@@ -11,6 +11,7 @@ using Avalonia.Controls.Selection;
 using Avalonia.Controls.Templates;
 using Avalonia.Data;
 using Avalonia.Input;
+using Avalonia.Interactivity;
 using Avalonia.LogicalTree;
 using Avalonia.Threading;
 
@@ -43,6 +44,18 @@ namespace Avalonia.Controls
         public static readonly DirectProperty<TreeViewItem, int> LevelProperty =
             AvaloniaProperty.RegisterDirect<TreeViewItem, int>(
                 nameof(Level), o => o.Level);
+        
+        /// <summary>
+        /// Defines the <see cref="Expanded"/> event.
+        /// </summary>
+        public static readonly RoutedEvent<RoutedEventArgs> ExpandedEvent =
+            RoutedEvent.Register<TreeViewItem, RoutedEventArgs>(nameof(Expanded), RoutingStrategies.Bubble | RoutingStrategies.Tunnel);
+        
+        /// <summary>
+        /// Defines the <see cref="Collapsed"/> event.
+        /// </summary>
+        public static readonly RoutedEvent<RoutedEventArgs> CollapsedEvent =
+            RoutedEvent.Register<TreeViewItem, RoutedEventArgs>(nameof(Collapsed), RoutingStrategies.Bubble | RoutingStrategies.Tunnel);
 
         private static readonly FuncTemplate<Panel?> DefaultPanel =
             new(() => new StackPanel());
@@ -65,6 +78,14 @@ namespace Avalonia.Controls
             ItemsPanelProperty.OverrideDefaultValue<TreeViewItem>(DefaultPanel);
             AutomationProperties.IsOffscreenBehaviorProperty.OverrideDefaultValue<TreeViewItem>(IsOffscreenBehavior.FromClip);
             RequestBringIntoViewEvent.AddClassHandler<TreeViewItem>((x, e) => x.OnRequestBringIntoView(e));
+            IsExpandedProperty.Changed.AddClassHandler<TreeViewItem, bool>((x, e) => x.OnIsExpandedChanged(e));
+        }
+
+        private void OnIsExpandedChanged(AvaloniaPropertyChangedEventArgs<bool> args)
+        {
+            var routedEvent = args.NewValue.Value ? ExpandedEvent : CollapsedEvent;
+            var eventArgs = new RoutedEventArgs() { RoutedEvent = routedEvent, Source = this };
+            TreeViewOwner?.RaiseEvent(eventArgs);
         }
 
         /// <summary>
@@ -93,6 +114,24 @@ namespace Avalonia.Controls
             get => _level;
             private set => SetAndRaise(LevelProperty, ref _level, value);
         }
+        
+        /// <summary>
+        /// Occurs after the <see cref="TreeViewItem"/> has expanded to show its children.
+        /// </summary>
+        public event EventHandler<RoutedEventArgs>? Expanded
+        {
+            add => AddHandler(ExpandedEvent, value);
+            remove => RemoveHandler(ExpandedEvent, value);
+        }
+        
+        /// <summary>
+        /// Occurs after the <see cref="TreeViewItem"/> has collapsed to hide its children.
+        /// </summary>
+        public event EventHandler<RoutedEventArgs>? Collapsed
+        {
+            add => AddHandler(CollapsedEvent, value);
+            remove => RemoveHandler(CollapsedEvent, value);
+        }
 
         internal TreeView? TreeViewOwner => _treeView;