Browse Source

Fix SplitView incorrectly closing when the user changes DisplayMode to inline when IsPaneOpen is already true (#19460)

* add a failing unit test for issue #19457

* fix #19457 by invalidating the pointerReleased subscription when DisplayMode changes.

* [SplitView] ensure we always set _pointerDisposable to null when disposing.
release/11.3.4
Dan Walmsley 6 months ago
committed by Julien Lebosquain
parent
commit
7ea790189b
  1. 32
      src/Avalonia.Controls/SplitView/SplitView.cs
  2. 40
      tests/Avalonia.Controls.UnitTests/SplitViewTests.cs

32
src/Avalonia.Controls/SplitView/SplitView.cs

@ -314,6 +314,7 @@ namespace Avalonia.Controls
{ {
base.OnDetachedFromVisualTree(e); base.OnDetachedFromVisualTree(e);
_pointerDisposable?.Dispose(); _pointerDisposable?.Dispose();
_pointerDisposable = null;
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -423,7 +424,7 @@ namespace Avalonia.Controls
protected virtual void OnPaneOpened(RoutedEventArgs args) protected virtual void OnPaneOpened(RoutedEventArgs args)
{ {
EnableLightDismiss(); InvalidateLightDismissSubscription();
RaiseEvent(args); RaiseEvent(args);
} }
@ -528,6 +529,8 @@ namespace Avalonia.Controls
}; };
TemplateSettings.ClosedPaneWidth = closedPaneWidth; TemplateSettings.ClosedPaneWidth = closedPaneWidth;
TemplateSettings.PaneColumnGridLength = paneColumnGridLength; TemplateSettings.PaneColumnGridLength = paneColumnGridLength;
InvalidateLightDismissSubscription();
} }
private void UpdateVisualStateForPanePlacementProperty(SplitViewPanePlacement newValue) private void UpdateVisualStateForPanePlacementProperty(SplitViewPanePlacement newValue)
@ -541,7 +544,7 @@ namespace Avalonia.Controls
PseudoClasses.Add(_lastPlacementPseudoclass); PseudoClasses.Add(_lastPlacementPseudoclass);
} }
private void EnableLightDismiss() private void InvalidateLightDismissSubscription()
{ {
if (_pane == null) if (_pane == null)
return; return;
@ -549,19 +552,26 @@ namespace Avalonia.Controls
// If this returns false, we're not in Overlay or CompactOverlay DisplayMode // If this returns false, we're not in Overlay or CompactOverlay DisplayMode
// and don't need the light dismiss behavior // and don't need the light dismiss behavior
if (!IsInOverlayMode()) if (!IsInOverlayMode())
{
_pointerDisposable?.Dispose();
_pointerDisposable = null;
return; return;
}
var topLevel = TopLevel.GetTopLevel(this); if (_pointerDisposable == null)
if (topLevel != null)
{ {
_pointerDisposable = Disposable.Create(() => var topLevel = TopLevel.GetTopLevel(this);
if (topLevel != null)
{ {
topLevel.PointerReleased -= PointerReleasedOutside; _pointerDisposable = Disposable.Create(() =>
topLevel.BackRequested -= TopLevelBackRequested; {
}); topLevel.PointerReleased -= PointerReleasedOutside;
topLevel.BackRequested -= TopLevelBackRequested;
topLevel.PointerReleased += PointerReleasedOutside; });
topLevel.BackRequested += TopLevelBackRequested;
topLevel.PointerReleased += PointerReleasedOutside;
topLevel.BackRequested += TopLevelBackRequested;
}
} }
} }

40
tests/Avalonia.Controls.UnitTests/SplitViewTests.cs

@ -303,5 +303,45 @@ namespace Avalonia.Controls.UnitTests
Assert.Contains(splitView.Classes, ":closed".Equals); Assert.Contains(splitView.Classes, ":closed".Equals);
} }
[Fact]
public void SplitView_Shouldnt_Close_Panel_When_IsPaneOpen_True_Then_Display_Mode_Changed()
{
using var app = UnitTestApplication.Start(TestServices.StyledWindow
.With(globalClock: new MockGlobalClock()));
var wnd = new Window
{
Width = 1280,
Height = 720
};
var splitView = new SplitView();
splitView.DisplayMode = SplitViewDisplayMode.CompactOverlay;
wnd.Content = splitView;
wnd.Show();
splitView.IsPaneOpen = true;
splitView.RaiseEvent(new PointerReleasedEventArgs(splitView,
null, wnd, new Point(1270, 30), 0,
new PointerPointProperties(),
KeyModifiers.None,
MouseButton.Left));
Assert.False(splitView.IsPaneOpen);
// Inline shouldn't close the pane
splitView.IsPaneOpen = true;
// Change the display mode once the pane is already open.
splitView.DisplayMode = SplitViewDisplayMode.Inline;
splitView.RaiseEvent(new PointerReleasedEventArgs(splitView,
null, wnd, new Point(1270, 30), 0,
new PointerPointProperties(),
KeyModifiers.None,
MouseButton.Left));
Assert.True(splitView.IsPaneOpen);
}
} }
} }

Loading…
Cancel
Save