From 0b51e0dbb75f4624b6b8deb59e3125013f042e87 Mon Sep 17 00:00:00 2001 From: robloo Date: Mon, 30 Jan 2023 23:06:47 -0500 Subject: [PATCH 1/7] Remove sender parameter from internal OnEvent methods --- src/Avalonia.Controls/SplitView.cs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Avalonia.Controls/SplitView.cs b/src/Avalonia.Controls/SplitView.cs index 35b135e152..200f0df607 100644 --- a/src/Avalonia.Controls/SplitView.cs +++ b/src/Avalonia.Controls/SplitView.cs @@ -206,24 +206,24 @@ namespace Avalonia.Controls if (value) { - OnPaneOpening(this, EventArgs.Empty); + OnPaneOpening(EventArgs.Empty); SetAndRaise(IsPaneOpenProperty, ref _isPaneOpen, value); PseudoClasses.Add(":open"); PseudoClasses.Remove(":closed"); - OnPaneOpened(this, EventArgs.Empty); + OnPaneOpened(EventArgs.Empty); } else { SplitViewPaneClosingEventArgs args = new SplitViewPaneClosingEventArgs(false); - OnPaneClosing(this, args); + OnPaneClosing(args); if (!args.Cancel) { SetAndRaise(IsPaneOpenProperty, ref _isPaneOpen, value); PseudoClasses.Add(":closed"); PseudoClasses.Remove(":open"); - OnPaneClosed(this, EventArgs.Empty); + OnPaneClosed(EventArgs.Empty); } } } @@ -394,24 +394,24 @@ namespace Avalonia.Controls return (DisplayMode == SplitViewDisplayMode.CompactOverlay || DisplayMode == SplitViewDisplayMode.Overlay); } - protected virtual void OnPaneOpening(SplitView sender, EventArgs args) + protected virtual void OnPaneOpening(EventArgs args) { - PaneOpening?.Invoke(sender, args); + PaneOpening?.Invoke(this, args); } - protected virtual void OnPaneOpened(SplitView sender, EventArgs args) + protected virtual void OnPaneOpened(EventArgs args) { - PaneOpened?.Invoke(sender, args); + PaneOpened?.Invoke(this, args); } - protected virtual void OnPaneClosing(SplitView sender, SplitViewPaneClosingEventArgs args) + protected virtual void OnPaneClosing(SplitViewPaneClosingEventArgs args) { - PaneClosing?.Invoke(sender, args); + PaneClosing?.Invoke(this, args); } - protected virtual void OnPaneClosed(SplitView sender, EventArgs args) + protected virtual void OnPaneClosed(EventArgs args) { - PaneClosed?.Invoke(sender, args); + PaneClosed?.Invoke(this, args); } private void OnCompactPaneLengthChanged(AvaloniaPropertyChangedEventArgs e) From 553deb41fd7285fa5e50c361ecfd13c9891f3561 Mon Sep 17 00:00:00 2001 From: robloo Date: Mon, 30 Jan 2023 23:34:20 -0500 Subject: [PATCH 2/7] Switch SplitView.IsPaneOpen to a StyledProperty Includes other small formatting changes and updates --- src/Avalonia.Controls/SplitView.cs | 141 +++++++++++++++++++---------- 1 file changed, 92 insertions(+), 49 deletions(-) diff --git a/src/Avalonia.Controls/SplitView.cs b/src/Avalonia.Controls/SplitView.cs index 200f0df607..b45e0f2adb 100644 --- a/src/Avalonia.Controls/SplitView.cs +++ b/src/Avalonia.Controls/SplitView.cs @@ -1,15 +1,13 @@ -using Avalonia.Controls.Metadata; +using System; +using Avalonia.Controls.Metadata; +using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; +using Avalonia.Controls.Templates; using Avalonia.Input; using Avalonia.Interactivity; +using Avalonia.LogicalTree; using Avalonia.Media; using Avalonia.Metadata; -using Avalonia.VisualTree; -using System; -using Avalonia.Reactive; -using Avalonia.Controls.Presenters; -using Avalonia.Controls.Templates; -using Avalonia.LogicalTree; namespace Avalonia.Controls { @@ -54,10 +52,13 @@ namespace Avalonia.Controls internal SplitViewTemplateSettings() { } public static readonly StyledProperty ClosedPaneWidthProperty = - AvaloniaProperty.Register(nameof(ClosedPaneWidth), 0d); + AvaloniaProperty.Register(nameof(ClosedPaneWidth), + 0d); public static readonly StyledProperty PaneColumnGridLengthProperty = - AvaloniaProperty.Register(nameof(PaneColumnGridLength)); + AvaloniaProperty.Register( + nameof(PaneColumnGridLength)); public double ClosedPaneWidth { @@ -93,26 +94,34 @@ namespace Avalonia.Controls /// Defines the property /// public static readonly StyledProperty CompactPaneLengthProperty = - AvaloniaProperty.Register(nameof(CompactPaneLength), defaultValue: 48); + AvaloniaProperty.Register( + nameof(CompactPaneLength), + defaultValue: 48); /// /// Defines the property /// public static readonly StyledProperty DisplayModeProperty = - AvaloniaProperty.Register(nameof(DisplayMode), defaultValue: SplitViewDisplayMode.Overlay); + AvaloniaProperty.Register( + nameof(DisplayMode), + defaultValue: SplitViewDisplayMode.Overlay); /// /// Defines the property /// - public static readonly DirectProperty IsPaneOpenProperty = - AvaloniaProperty.RegisterDirect(nameof(IsPaneOpen), - x => x.IsPaneOpen, (x, v) => x.IsPaneOpen = v); + public static readonly StyledProperty IsPaneOpenProperty = + AvaloniaProperty.Register( + nameof(IsPaneOpen), + defaultValue: false, + coerce: CoerceIsPaneOpen); /// /// Defines the property /// public static readonly StyledProperty OpenPaneLengthProperty = - AvaloniaProperty.Register(nameof(OpenPaneLength), defaultValue: 320); + AvaloniaProperty.Register( + nameof(OpenPaneLength), + defaultValue: 320); /// /// Defines the property @@ -150,7 +159,6 @@ namespace Avalonia.Controls public static readonly StyledProperty TemplateSettingsProperty = AvaloniaProperty.Register(nameof(TemplateSettings)); - private bool _isPaneOpen; private Panel? _pane; private IDisposable? _pointerDisposable; @@ -169,7 +177,7 @@ namespace Avalonia.Controls PanePlacementProperty.Changed.AddClassHandler((x, v) => x.OnPanePlacementChanged(v)); DisplayModeProperty.Changed.AddClassHandler((x, v) => x.OnDisplayModeChanged(v)); - PaneProperty.Changed.AddClassHandler((x, e) => x.PaneChanged(e)); + PaneProperty.Changed.AddClassHandler((x, e) => x.OnPaneChanged(e)); } /// @@ -196,37 +204,8 @@ namespace Avalonia.Controls /// public bool IsPaneOpen { - get => _isPaneOpen; - set - { - if (value == _isPaneOpen) - { - return; - } - - if (value) - { - OnPaneOpening(EventArgs.Empty); - SetAndRaise(IsPaneOpenProperty, ref _isPaneOpen, value); - - PseudoClasses.Add(":open"); - PseudoClasses.Remove(":closed"); - OnPaneOpened(EventArgs.Empty); - } - else - { - SplitViewPaneClosingEventArgs args = new SplitViewPaneClosingEventArgs(false); - OnPaneClosing(args); - if (!args.Cancel) - { - SetAndRaise(IsPaneOpenProperty, ref _isPaneOpen, value); - - PseudoClasses.Add(":closed"); - PseudoClasses.Remove(":open"); - OnPaneClosed(EventArgs.Empty); - } - } - } + get => GetValue(IsPaneOpenProperty); + set => SetValue(IsPaneOpenProperty, value); } /// @@ -351,6 +330,30 @@ namespace Avalonia.Controls _pointerDisposable?.Dispose(); } + /// + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == IsPaneOpenProperty) + { + bool isPaneOpen = change.GetNewValue(); + + if (isPaneOpen) + { + PseudoClasses.Add(":open"); + PseudoClasses.Remove(":closed"); + OnPaneOpened(EventArgs.Empty); + } + else + { + PseudoClasses.Add(":closed"); + PseudoClasses.Remove(":open"); + OnPaneClosed(EventArgs.Empty); + } + } + } + private void PointerPressedOutside(object? sender, PointerPressedEventArgs e) { if (!IsPaneOpen) @@ -485,7 +488,7 @@ namespace Avalonia.Controls PseudoClasses.Set(":lightdismiss", mode); } - private void PaneChanged(AvaloniaPropertyChangedEventArgs e) + private void OnPaneChanged(AvaloniaPropertyChangedEventArgs e) { if (e.OldValue is ILogical oldChild) { @@ -497,5 +500,45 @@ namespace Avalonia.Controls LogicalChildren.Add(newChild); } } + + /// + /// Called when the property has to be coerced. + /// + /// The value to coerce. + protected virtual bool OnCoerceIsPaneOpen(bool value) + { + if (value) + { + OnPaneOpening(EventArgs.Empty); + } + else + { + var eventArgs = new SplitViewPaneClosingEventArgs(false); + OnPaneClosing(eventArgs); + + if (eventArgs.Cancel) + { + return !value; + } + } + + return value; + } + + /// + /// Coerces/validates the property value. + /// + /// The instance. + /// The value to coerce. + /// The coerced/validated value. + private static bool CoerceIsPaneOpen(AvaloniaObject instance, bool value) + { + if (instance is SplitView splitView) + { + return splitView.OnCoerceIsPaneOpen(value); + } + + return value; + } } } From cc1cf2003a62fc6653a392f094b978a162e9e79b Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 18 Feb 2023 20:29:22 -0500 Subject: [PATCH 3/7] Separate out SplitView types and move to SplitView directory --- .../{ => SplitView}/SplitView.cs | 62 ------------------- .../SplitView/SplitViewDisplayMode.cs | 29 +++++++++ .../SplitViewPaneClosingEventArgs.cs | 0 .../SplitView/SplitViewPanePlacement.cs | 18 ++++++ .../SplitView/SplitViewTemplateSettings.cs | 32 ++++++++++ 5 files changed, 79 insertions(+), 62 deletions(-) rename src/Avalonia.Controls/{ => SplitView}/SplitView.cs (89%) create mode 100644 src/Avalonia.Controls/SplitView/SplitViewDisplayMode.cs rename src/Avalonia.Controls/{ => SplitView}/SplitViewPaneClosingEventArgs.cs (100%) create mode 100644 src/Avalonia.Controls/SplitView/SplitViewPanePlacement.cs create mode 100644 src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs diff --git a/src/Avalonia.Controls/SplitView.cs b/src/Avalonia.Controls/SplitView/SplitView.cs similarity index 89% rename from src/Avalonia.Controls/SplitView.cs rename to src/Avalonia.Controls/SplitView/SplitView.cs index b45e0f2adb..35faf8605d 100644 --- a/src/Avalonia.Controls/SplitView.cs +++ b/src/Avalonia.Controls/SplitView/SplitView.cs @@ -11,68 +11,6 @@ using Avalonia.Metadata; namespace Avalonia.Controls { - /// - /// Defines constants for how the SplitView Pane should display - /// - public enum SplitViewDisplayMode - { - /// - /// Pane is displayed next to content, and does not auto collapse - /// when tapped outside - /// - Inline, - /// - /// Pane is displayed next to content. When collapsed, pane is still - /// visible according to CompactPaneLength. Pane does not auto collapse - /// when tapped outside - /// - CompactInline, - /// - /// Pane is displayed above content. Pane collapses when tapped outside - /// - Overlay, - /// - /// Pane is displayed above content. When collapsed, pane is still - /// visible according to CompactPaneLength. Pane collapses when tapped outside - /// - CompactOverlay - } - - /// - /// Defines constants for where the Pane should appear - /// - public enum SplitViewPanePlacement - { - Left, - Right - } - - public class SplitViewTemplateSettings : AvaloniaObject - { - internal SplitViewTemplateSettings() { } - - public static readonly StyledProperty ClosedPaneWidthProperty = - AvaloniaProperty.Register(nameof(ClosedPaneWidth), - 0d); - - public static readonly StyledProperty PaneColumnGridLengthProperty = - AvaloniaProperty.Register( - nameof(PaneColumnGridLength)); - - public double ClosedPaneWidth - { - get => GetValue(ClosedPaneWidthProperty); - internal set => SetValue(ClosedPaneWidthProperty, value); - } - - public GridLength PaneColumnGridLength - { - get => GetValue(PaneColumnGridLengthProperty); - internal set => SetValue(PaneColumnGridLengthProperty, value); - } - } - /// /// A control with two views: A collapsible pane and an area for content /// diff --git a/src/Avalonia.Controls/SplitView/SplitViewDisplayMode.cs b/src/Avalonia.Controls/SplitView/SplitViewDisplayMode.cs new file mode 100644 index 0000000000..6333f96f86 --- /dev/null +++ b/src/Avalonia.Controls/SplitView/SplitViewDisplayMode.cs @@ -0,0 +1,29 @@ +namespace Avalonia.Controls +{ + /// + /// Defines constants for how the SplitView Pane should display + /// + public enum SplitViewDisplayMode + { + /// + /// Pane is displayed next to content, and does not auto collapse + /// when tapped outside + /// + Inline, + /// + /// Pane is displayed next to content. When collapsed, pane is still + /// visible according to CompactPaneLength. Pane does not auto collapse + /// when tapped outside + /// + CompactInline, + /// + /// Pane is displayed above content. Pane collapses when tapped outside + /// + Overlay, + /// + /// Pane is displayed above content. When collapsed, pane is still + /// visible according to CompactPaneLength. Pane collapses when tapped outside + /// + CompactOverlay + } +} diff --git a/src/Avalonia.Controls/SplitViewPaneClosingEventArgs.cs b/src/Avalonia.Controls/SplitView/SplitViewPaneClosingEventArgs.cs similarity index 100% rename from src/Avalonia.Controls/SplitViewPaneClosingEventArgs.cs rename to src/Avalonia.Controls/SplitView/SplitViewPaneClosingEventArgs.cs diff --git a/src/Avalonia.Controls/SplitView/SplitViewPanePlacement.cs b/src/Avalonia.Controls/SplitView/SplitViewPanePlacement.cs new file mode 100644 index 0000000000..62c5387192 --- /dev/null +++ b/src/Avalonia.Controls/SplitView/SplitViewPanePlacement.cs @@ -0,0 +1,18 @@ +namespace Avalonia.Controls +{ + /// + /// Defines constants for where the Pane should appear + /// + public enum SplitViewPanePlacement + { + /// + /// The pane is shown to the left of content. + /// + Left, + + /// + /// The pane is shown to the right of content. + /// + Right + } +} diff --git a/src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs b/src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs new file mode 100644 index 0000000000..f2cbf55986 --- /dev/null +++ b/src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs @@ -0,0 +1,32 @@ +namespace Avalonia.Controls.Primitives +{ + /// + /// Provides calculated values for use with the 's control theme or template. + /// This class is NOT intended for general use. + /// + public class SplitViewTemplateSettings : AvaloniaObject + { + internal SplitViewTemplateSettings() { } + + public static readonly StyledProperty ClosedPaneWidthProperty = + AvaloniaProperty.Register(nameof(ClosedPaneWidth), + 0d); + + public static readonly StyledProperty PaneColumnGridLengthProperty = + AvaloniaProperty.Register( + nameof(PaneColumnGridLength)); + + public double ClosedPaneWidth + { + get => GetValue(ClosedPaneWidthProperty); + internal set => SetValue(ClosedPaneWidthProperty, value); + } + + public GridLength PaneColumnGridLength + { + get => GetValue(PaneColumnGridLengthProperty); + internal set => SetValue(PaneColumnGridLengthProperty, value); + } + } +} From 11f09232d3bf7b376f0ff7091365800f6266df7e Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 18 Feb 2023 20:59:36 -0500 Subject: [PATCH 4/7] Use OnPropertyChanged override method for all SplitView change handling --- src/Avalonia.Controls/SplitView/SplitView.cs | 135 +++++++++---------- 1 file changed, 65 insertions(+), 70 deletions(-) diff --git a/src/Avalonia.Controls/SplitView/SplitView.cs b/src/Avalonia.Controls/SplitView/SplitView.cs index 35faf8605d..da8190d764 100644 --- a/src/Avalonia.Controls/SplitView/SplitView.cs +++ b/src/Avalonia.Controls/SplitView/SplitView.cs @@ -110,12 +110,6 @@ namespace Avalonia.Controls static SplitView() { - UseLightDismissOverlayModeProperty.Changed.AddClassHandler((x, v) => x.OnUseLightDismissChanged(v)); - CompactPaneLengthProperty.Changed.AddClassHandler((x, v) => x.OnCompactPaneLengthChanged(v)); - PanePlacementProperty.Changed.AddClassHandler((x, v) => x.OnPanePlacementChanged(v)); - DisplayModeProperty.Changed.AddClassHandler((x, v) => x.OnDisplayModeChanged(v)); - - PaneProperty.Changed.AddClassHandler((x, e) => x.OnPaneChanged(e)); } /// @@ -273,7 +267,40 @@ namespace Avalonia.Controls { base.OnPropertyChanged(change); - if (change.Property == IsPaneOpenProperty) + if (change.Property == CompactPaneLengthProperty) + { + var newLen = change.GetNewValue(); + var displayMode = DisplayMode; + if (displayMode == SplitViewDisplayMode.CompactInline) + { + TemplateSettings.ClosedPaneWidth = newLen; + } + else if (displayMode == SplitViewDisplayMode.CompactOverlay) + { + TemplateSettings.ClosedPaneWidth = newLen; + TemplateSettings.PaneColumnGridLength = new GridLength(newLen, GridUnitType.Pixel); + } + } + else if (change.Property == DisplayModeProperty) + { + var oldState = GetPseudoClass(change.GetOldValue()); + var newState = GetPseudoClass(change.GetNewValue()); + + PseudoClasses.Remove($":{oldState}"); + PseudoClasses.Add($":{newState}"); + + var (closedPaneWidth, paneColumnGridLength) = change.GetNewValue() switch + { + SplitViewDisplayMode.Overlay => (0, new GridLength(0, GridUnitType.Pixel)), + SplitViewDisplayMode.CompactOverlay => (CompactPaneLength, new GridLength(CompactPaneLength, GridUnitType.Pixel)), + SplitViewDisplayMode.Inline => (0, new GridLength(0, GridUnitType.Auto)), + SplitViewDisplayMode.CompactInline => (CompactPaneLength, new GridLength(0, GridUnitType.Auto)), + _ => throw new NotImplementedException(), + }; + TemplateSettings.ClosedPaneWidth = closedPaneWidth; + TemplateSettings.PaneColumnGridLength = paneColumnGridLength; + } + else if (change.Property == IsPaneOpenProperty) { bool isPaneOpen = change.GetNewValue(); @@ -290,6 +317,30 @@ namespace Avalonia.Controls OnPaneClosed(EventArgs.Empty); } } + else if (change.Property == PaneProperty) + { + if (change.OldValue is ILogical oldChild) + { + LogicalChildren.Remove(oldChild); + } + + if (change.NewValue is ILogical newChild) + { + LogicalChildren.Add(newChild); + } + } + else if (change.Property == PanePlacementProperty) + { + var oldState = GetPseudoClass(change.GetOldValue()); + var newState = GetPseudoClass(change.GetNewValue()); + PseudoClasses.Remove($":{oldState}"); + PseudoClasses.Add($":{newState}"); + } + else if (change.Property == UseLightDismissOverlayModeProperty) + { + var mode = change.GetNewValue(); + PseudoClasses.Set(":lightdismiss", mode); + } } private void PointerPressedOutside(object? sender, PointerPressedEventArgs e) @@ -325,7 +376,7 @@ namespace Avalonia.Controls } if (closePane) { - IsPaneOpen = false; + SetCurrentValue(IsPaneOpenProperty, false); e.Handled = true; } } @@ -355,21 +406,9 @@ namespace Avalonia.Controls PaneClosed?.Invoke(this, args); } - private void OnCompactPaneLengthChanged(AvaloniaPropertyChangedEventArgs e) - { - var newLen = (double)e.NewValue!; - var displayMode = DisplayMode; - if (displayMode == SplitViewDisplayMode.CompactInline) - { - TemplateSettings.ClosedPaneWidth = newLen; - } - else if (displayMode == SplitViewDisplayMode.CompactOverlay) - { - TemplateSettings.ClosedPaneWidth = newLen; - TemplateSettings.PaneColumnGridLength = new GridLength(newLen, GridUnitType.Pixel); - } - } - + /// + /// Gets the appropriate PseudoClass for the given . + /// private static string GetPseudoClass(SplitViewDisplayMode mode) { return mode switch @@ -382,6 +421,9 @@ namespace Avalonia.Controls }; } + /// + /// Gets the appropriate PseudoClass for the given . + /// private static string GetPseudoClass(SplitViewPanePlacement placement) { return placement switch @@ -392,53 +434,6 @@ namespace Avalonia.Controls }; } - private void OnPanePlacementChanged(AvaloniaPropertyChangedEventArgs e) - { - var oldState = GetPseudoClass(e.GetOldValue()); - var newState = GetPseudoClass(e.GetNewValue()); - PseudoClasses.Remove($":{oldState}"); - PseudoClasses.Add($":{newState}"); - } - - private void OnDisplayModeChanged(AvaloniaPropertyChangedEventArgs e) - { - var oldState = GetPseudoClass(e.GetOldValue()); - var newState = GetPseudoClass(e.GetNewValue()); - - PseudoClasses.Remove($":{oldState}"); - PseudoClasses.Add($":{newState}"); - - var (closedPaneWidth, paneColumnGridLength) = e.GetNewValue() switch - { - SplitViewDisplayMode.Overlay => (0, new GridLength(0, GridUnitType.Pixel)), - SplitViewDisplayMode.CompactOverlay => (CompactPaneLength, new GridLength(CompactPaneLength, GridUnitType.Pixel)), - SplitViewDisplayMode.Inline => (0, new GridLength(0, GridUnitType.Auto)), - SplitViewDisplayMode.CompactInline => (CompactPaneLength, new GridLength(0, GridUnitType.Auto)), - _ => throw new NotImplementedException(), - }; - TemplateSettings.ClosedPaneWidth = closedPaneWidth; - TemplateSettings.PaneColumnGridLength = paneColumnGridLength; - } - - private void OnUseLightDismissChanged(AvaloniaPropertyChangedEventArgs e) - { - var mode = (bool)e.NewValue!; - PseudoClasses.Set(":lightdismiss", mode); - } - - private void OnPaneChanged(AvaloniaPropertyChangedEventArgs e) - { - if (e.OldValue is ILogical oldChild) - { - LogicalChildren.Remove(oldChild); - } - - if (e.NewValue is ILogical newChild) - { - LogicalChildren.Add(newChild); - } - } - /// /// Called when the property has to be coerced. /// From 1018a7779565d185aa2f1c12775ede2f9ba0c8c3 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 18 Feb 2023 21:25:19 -0500 Subject: [PATCH 5/7] Switch to routed events in SplitView and support cancellation in opening/closing --- src/Avalonia.Controls/SplitView/SplitView.cs | 109 +++++++++++++++---- 1 file changed, 85 insertions(+), 24 deletions(-) diff --git a/src/Avalonia.Controls/SplitView/SplitView.cs b/src/Avalonia.Controls/SplitView/SplitView.cs index da8190d764..1099a40f08 100644 --- a/src/Avalonia.Controls/SplitView/SplitView.cs +++ b/src/Avalonia.Controls/SplitView/SplitView.cs @@ -97,6 +97,38 @@ namespace Avalonia.Controls public static readonly StyledProperty TemplateSettingsProperty = AvaloniaProperty.Register(nameof(TemplateSettings)); + /// + /// Defines the event. + /// + public static readonly RoutedEvent PaneClosedEvent = + RoutedEvent.Register( + nameof(PaneClosed), + RoutingStrategies.Bubble); + + /// + /// Defines the event. + /// + public static readonly RoutedEvent PaneClosingEvent = + RoutedEvent.Register( + nameof(PaneClosing), + RoutingStrategies.Bubble); + + /// + /// Defines the event. + /// + public static readonly RoutedEvent PaneOpenedEvent = + RoutedEvent.Register( + nameof(PaneOpened), + RoutingStrategies.Bubble); + + /// + /// Defines the event. + /// + public static readonly RoutedEvent PaneOpeningEvent = + RoutedEvent.Register( + nameof(PaneOpening), + RoutingStrategies.Bubble); + private Panel? _pane; private IDisposable? _pointerDisposable; @@ -208,24 +240,48 @@ namespace Avalonia.Controls } /// - /// Fired when the pane is closed + /// Fired when the pane is closed. /// - public event EventHandler? PaneClosed; + public event EventHandler? PaneClosed + { + add => AddHandler(PaneClosedEvent, value); + remove => RemoveHandler(PaneClosedEvent, value); + } /// - /// Fired when the pane is closing + /// Fired when the pane is closing. /// - public event EventHandler? PaneClosing; + /// + /// The event args property may be set to true to cancel the event + /// and keep the pane open. + /// + public event EventHandler? PaneClosing + { + add => AddHandler(PaneClosingEvent, value); + remove => RemoveHandler(PaneClosingEvent, value); + } /// - /// Fired when the pane is opened + /// Fired when the pane is opened. /// - public event EventHandler? PaneOpened; + public event EventHandler? PaneOpened + { + add => AddHandler(PaneOpenedEvent, value); + remove => RemoveHandler(PaneOpenedEvent, value); + } /// - /// Fired when the pane is opening + /// Fired when the pane is opening. /// - public event EventHandler? PaneOpening; + /// + /// The event args property may be set to true to cancel the event + /// and keep the pane closed. + /// + public event EventHandler? PaneOpening + { + add => AddHandler(PaneOpeningEvent, value); + remove => RemoveHandler(PaneOpeningEvent, value); + } protected override bool RegisterContentPresenter(IContentPresenter presenter) { @@ -308,13 +364,15 @@ namespace Avalonia.Controls { PseudoClasses.Add(":open"); PseudoClasses.Remove(":closed"); - OnPaneOpened(EventArgs.Empty); + + OnPaneOpened(new RoutedEventArgs(PaneOpenedEvent, this)); } else { PseudoClasses.Add(":closed"); PseudoClasses.Remove(":open"); - OnPaneClosed(EventArgs.Empty); + + OnPaneClosed(new RoutedEventArgs(PaneClosedEvent, this)); } } else if (change.Property == PaneProperty) @@ -386,24 +444,24 @@ namespace Avalonia.Controls return (DisplayMode == SplitViewDisplayMode.CompactOverlay || DisplayMode == SplitViewDisplayMode.Overlay); } - protected virtual void OnPaneOpening(EventArgs args) + protected virtual void OnPaneOpening(CancelRoutedEventArgs args) { - PaneOpening?.Invoke(this, args); + RaiseEvent(args); } - protected virtual void OnPaneOpened(EventArgs args) + protected virtual void OnPaneOpened(RoutedEventArgs args) { - PaneOpened?.Invoke(this, args); + RaiseEvent(args); } - protected virtual void OnPaneClosing(SplitViewPaneClosingEventArgs args) + protected virtual void OnPaneClosing(CancelRoutedEventArgs args) { - PaneClosing?.Invoke(this, args); + RaiseEvent(args); } - protected virtual void OnPaneClosed(EventArgs args) + protected virtual void OnPaneClosed(RoutedEventArgs args) { - PaneClosed?.Invoke(this, args); + RaiseEvent(args); } /// @@ -440,19 +498,22 @@ namespace Avalonia.Controls /// The value to coerce. protected virtual bool OnCoerceIsPaneOpen(bool value) { + CancelRoutedEventArgs eventArgs; + if (value) { - OnPaneOpening(EventArgs.Empty); + eventArgs = new CancelRoutedEventArgs(PaneOpeningEvent, this); + OnPaneOpening(eventArgs); } else { - var eventArgs = new SplitViewPaneClosingEventArgs(false); + eventArgs = new CancelRoutedEventArgs(PaneClosingEvent, this); OnPaneClosing(eventArgs); + } - if (eventArgs.Cancel) - { - return !value; - } + if (eventArgs.Cancel) + { + return !value; } return value; From 937b07f339fb1d801e071ac8d3f7bd1a464a1bd4 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 18 Feb 2023 21:26:34 -0500 Subject: [PATCH 6/7] Remove SplitViewPaneClosingEventArgs --- .../SplitView/SplitViewPaneClosingEventArgs.cs | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 src/Avalonia.Controls/SplitView/SplitViewPaneClosingEventArgs.cs diff --git a/src/Avalonia.Controls/SplitView/SplitViewPaneClosingEventArgs.cs b/src/Avalonia.Controls/SplitView/SplitViewPaneClosingEventArgs.cs deleted file mode 100644 index 46fb2d161b..0000000000 --- a/src/Avalonia.Controls/SplitView/SplitViewPaneClosingEventArgs.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace Avalonia.Controls -{ - public class SplitViewPaneClosingEventArgs : EventArgs - { - public bool Cancel { get; set; } - - public SplitViewPaneClosingEventArgs(bool cancel) - { - Cancel = cancel; - } - } -} From afbb04b5ffe4fe133de16f63dfcd14323656833a Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 18 Feb 2023 21:26:49 -0500 Subject: [PATCH 7/7] Fix eventArgs type in Expander --- src/Avalonia.Controls/Expander.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Expander.cs b/src/Avalonia.Controls/Expander.cs index 2ad6a58d38..668de5bca9 100644 --- a/src/Avalonia.Controls/Expander.cs +++ b/src/Avalonia.Controls/Expander.cs @@ -191,7 +191,7 @@ namespace Avalonia.Controls /// /// Invoked just before the event. /// - protected virtual void OnCollapsing(RoutedEventArgs eventArgs) + protected virtual void OnCollapsing(CancelRoutedEventArgs eventArgs) { RaiseEvent(eventArgs); } @@ -207,7 +207,7 @@ namespace Avalonia.Controls /// /// Invoked just before the event. /// - protected virtual void OnExpanding(RoutedEventArgs eventArgs) + protected virtual void OnExpanding(CancelRoutedEventArgs eventArgs) { RaiseEvent(eventArgs); }