diff --git a/src/Avalonia.Base/LogicalTree/ChildIndexChangedEventArgs.cs b/src/Avalonia.Base/LogicalTree/ChildIndexChangedEventArgs.cs index 8f2be75e0f..6b41c1c66c 100644 --- a/src/Avalonia.Base/LogicalTree/ChildIndexChangedEventArgs.cs +++ b/src/Avalonia.Base/LogicalTree/ChildIndexChangedEventArgs.cs @@ -1,26 +1,59 @@ -#nullable enable -using System; +using System; + +#nullable enable namespace Avalonia.LogicalTree { /// - /// Event args for event. + /// Describes the action that caused a event. /// - public class ChildIndexChangedEventArgs : EventArgs + public enum ChildIndexChangedAction { - public static new ChildIndexChangedEventArgs Empty { get; } = new ChildIndexChangedEventArgs(); + /// + /// The index of a single child changed. + /// + ChildIndexChanged, - private ChildIndexChangedEventArgs() - { - Index = -1; - } + /// + /// The index of multiple children changed and all children should be re-evaluated. + /// + ChildIndexesReset, + + /// + /// The total number of children changed. + /// + TotalCountChanged, + } + /// + /// Event args for event. + /// + public class ChildIndexChangedEventArgs : EventArgs + { + /// + /// Initializes a new instance of the class with + /// an action of . + /// + /// The child whose index was changed. + /// The new index of the child. public ChildIndexChangedEventArgs(ILogical child, int index) { + Action = ChildIndexChangedAction.ChildIndexChanged; Child = child; Index = index; } + private ChildIndexChangedEventArgs(ChildIndexChangedAction action) + { + Action = action; + Index = -1; + } + + /// + /// Gets the type of change action that ocurred on the list control. + /// + public ChildIndexChangedAction Action { get; } + /// /// Gets the logical child whose index was changed or null if all children should be re-evaluated. /// @@ -30,5 +63,17 @@ namespace Avalonia.LogicalTree /// Gets the new index of or -1 if all children should be re-evaluated. /// public int Index { get; } + + /// + /// Gets an instance of the with an action of + /// . + /// + public static ChildIndexChangedEventArgs ChildIndexesReset { get; } = new(ChildIndexChangedAction.ChildIndexesReset); + + /// + /// Gets an instance of the with an action of + /// . + /// + public static ChildIndexChangedEventArgs TotalCountChanged { get; } = new(ChildIndexChangedAction.TotalCountChanged); } } diff --git a/src/Avalonia.Base/LogicalTree/IChildIndexProvider.cs b/src/Avalonia.Base/LogicalTree/IChildIndexProvider.cs index a5e191d63e..186c9527f2 100644 --- a/src/Avalonia.Base/LogicalTree/IChildIndexProvider.cs +++ b/src/Avalonia.Base/LogicalTree/IChildIndexProvider.cs @@ -28,10 +28,5 @@ namespace Avalonia.LogicalTree /// Notifies subscriber when a child's index was changed. /// event EventHandler? ChildIndexChanged; - - /// - /// Notifies subscriber when the total child count changes. - /// - event EventHandler? TotalCountChanged; } } diff --git a/src/Avalonia.Base/Styling/Activators/NthChildActivator.cs b/src/Avalonia.Base/Styling/Activators/NthChildActivator.cs index e0fa056765..8bdcec2e53 100644 --- a/src/Avalonia.Base/Styling/Activators/NthChildActivator.cs +++ b/src/Avalonia.Base/Styling/Activators/NthChildActivator.cs @@ -37,7 +37,6 @@ namespace Avalonia.Styling.Activators protected override void Initialize() { _provider.ChildIndexChanged += ChildIndexChanged; - _provider.TotalCountChanged += TotalCountChanged; } protected override void Deinitialize() @@ -48,9 +47,11 @@ namespace Avalonia.Styling.Activators private void ChildIndexChanged(object? sender, ChildIndexChangedEventArgs e) { // Run matching again if: - // 1. e.Child is null, when all children indices were changed. - // 2. Subscribed child index was changed. - if (e.Child is null || e.Child == _control) + // 1. Subscribed child index was changed + // 2. Child indexes were reset + // 3. We're a reversed (nth-last-child) selector and total count has changed + if ((e.Child == _control || e.Action == ChildIndexChangedAction.ChildIndexesReset) || + (_reversed && e.Action == ChildIndexChangedAction.TotalCountChanged)) { // We're using the _index field to pass the index of the child to EvaluateIsActive // *only* when the active state is re-evaluated via this event handler. The docs diff --git a/src/Avalonia.Controls.DataGrid/Primitives/DataGridCellsPresenter.cs b/src/Avalonia.Controls.DataGrid/Primitives/DataGridCellsPresenter.cs index 06a77f0894..f5db7c0855 100644 --- a/src/Avalonia.Controls.DataGrid/Primitives/DataGridCellsPresenter.cs +++ b/src/Avalonia.Controls.DataGrid/Primitives/DataGridCellsPresenter.cs @@ -336,7 +336,7 @@ namespace Avalonia.Controls.Primitives internal void InvalidateChildIndex() { - _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty); + _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.ChildIndexesReset); } private bool ShouldDisplayCell(DataGridColumn column, double frozenLeftEdge, double scrollingLeftEdge) diff --git a/src/Avalonia.Controls.DataGrid/Primitives/DataGridColumnHeadersPresenter.cs b/src/Avalonia.Controls.DataGrid/Primitives/DataGridColumnHeadersPresenter.cs index f9b84793c6..fcf72385b2 100644 --- a/src/Avalonia.Controls.DataGrid/Primitives/DataGridColumnHeadersPresenter.cs +++ b/src/Avalonia.Controls.DataGrid/Primitives/DataGridColumnHeadersPresenter.cs @@ -423,7 +423,7 @@ namespace Avalonia.Controls.Primitives internal void InvalidateChildIndex() { - _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty); + _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.ChildIndexesReset); } } } diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 8c3c65a6a7..9483f98881 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -101,7 +101,6 @@ namespace Avalonia.Controls private int _itemCount; private ItemContainerGenerator? _itemContainerGenerator; private EventHandler? _childIndexChanged; - private EventHandler? _totalCountChanged; private IDataTemplate? _displayMemberItemTemplate; private ScrollViewer? _scrollViewer; private ItemsPresenter? _itemsPresenter; @@ -218,12 +217,6 @@ namespace Avalonia.Controls remove => _childIndexChanged -= value; } - event EventHandler? IChildIndexProvider.TotalCountChanged - { - add => _totalCountChanged += value; - remove => _totalCountChanged -= value; - } - /// public event EventHandler HorizontalSnapPointsChanged { @@ -500,7 +493,7 @@ namespace Avalonia.Controls else if (change.Property == ItemCountProperty) { UpdatePseudoClasses(change.GetNewValue()); - _totalCountChanged?.Invoke(this, EventArgs.Empty); + _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.TotalCountChanged); } else if (change.Property == ItemContainerThemeProperty && _itemContainerGenerator is not null) { @@ -585,7 +578,7 @@ namespace Avalonia.Controls internal void RegisterItemsPresenter(ItemsPresenter presenter) { Presenter = presenter; - _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty); + _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.ChildIndexesReset); } internal void PrepareItemContainer(Control container, object? item, int index) diff --git a/src/Avalonia.Controls/Panel.cs b/src/Avalonia.Controls/Panel.cs index 3006efb7de..10391afca2 100644 --- a/src/Avalonia.Controls/Panel.cs +++ b/src/Avalonia.Controls/Panel.cs @@ -35,7 +35,6 @@ namespace Avalonia.Controls } private EventHandler? _childIndexChanged; - private EventHandler? _totalCountChanged; /// /// Initializes a new instance of the class. @@ -67,12 +66,6 @@ namespace Avalonia.Controls remove => _childIndexChanged -= value; } - event EventHandler? IChildIndexProvider.TotalCountChanged - { - add => _totalCountChanged += value; - remove => _totalCountChanged -= value; - } - /// /// Renders the visual to a . /// @@ -161,7 +154,7 @@ namespace Avalonia.Controls throw new NotSupportedException(); } - _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty); + _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.ChildIndexesReset); InvalidateMeasureOnChildrenChanged(); } @@ -173,7 +166,7 @@ namespace Avalonia.Controls private void ChildrenPropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(Children.Count) || e.PropertyName is null) - _totalCountChanged?.Invoke(this, EventArgs.Empty); + _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.TotalCountChanged); } private static void AffectsParentArrangeInvalidate(AvaloniaPropertyChangedEventArgs e)