From ea5623df7e645936ff94fdd29543c259fb8e1142 Mon Sep 17 00:00:00 2001
From: amwx <40413319+amwx@users.noreply.github.com>
Date: Fri, 17 Mar 2023 15:27:26 -0400
Subject: [PATCH] Fix initial state/overlay & make TemplateSettings a readonly
DirectProperty
---
src/Avalonia.Controls/SplitView/SplitView.cs | 124 ++++++++++++-------
1 file changed, 76 insertions(+), 48 deletions(-)
diff --git a/src/Avalonia.Controls/SplitView/SplitView.cs b/src/Avalonia.Controls/SplitView/SplitView.cs
index 1099a40f08..a5c87f5843 100644
--- a/src/Avalonia.Controls/SplitView/SplitView.cs
+++ b/src/Avalonia.Controls/SplitView/SplitView.cs
@@ -94,8 +94,9 @@ namespace Avalonia.Controls
///
/// Defines the property
///
- public static readonly StyledProperty TemplateSettingsProperty =
- AvaloniaProperty.Register(nameof(TemplateSettings));
+ public static readonly DirectProperty TemplateSettingsProperty =
+ AvaloniaProperty.RegisterDirect(nameof(TemplateSettings),
+ x => x.TemplateSettings);
///
/// Defines the event.
@@ -131,12 +132,12 @@ namespace Avalonia.Controls
private Panel? _pane;
private IDisposable? _pointerDisposable;
+ private SplitViewTemplateSettings _templateSettings;
+ private string _lastDisplayModePseudoclass;
+ private string _lastPlacementPseudoclass;
public SplitView()
{
- PseudoClasses.Add(":overlay");
- PseudoClasses.Add(":left");
-
TemplateSettings = new SplitViewTemplateSettings();
}
@@ -208,7 +209,7 @@ namespace Avalonia.Controls
get => GetValue(PaneProperty);
set => SetValue(PaneProperty, value);
}
-
+
///
/// Gets or sets the data template used to display the header content of the control.
///
@@ -235,8 +236,8 @@ namespace Avalonia.Controls
///
public SplitViewTemplateSettings TemplateSettings
{
- get => GetValue(TemplateSettingsProperty);
- set => SetValue(TemplateSettingsProperty, value);
+ get => _templateSettings;
+ private set => SetAndRaise(TemplateSettingsProperty, ref _templateSettings, value);
}
///
@@ -291,7 +292,7 @@ namespace Avalonia.Controls
{
return true;
}
-
+
return result;
}
@@ -299,12 +300,20 @@ namespace Avalonia.Controls
{
base.OnApplyTemplate(e);
_pane = e.NameScope.Find("PART_PaneRoot");
+
+ UpdateVisualStateForCompactPaneLength(CompactPaneLength);
+ UpdateVisualStateForDisplayMode(DisplayMode);
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
+ // :left and :right style triggers contain the template so we need to do this as
+ // soon as we're attached so the template applies. The other visual states can
+ // be updated after the template applies
+ UpdateVisualStateForPanePlacementProperty(PanePlacement);
+
var topLevel = this.VisualRoot;
if (topLevel is Window window)
{
@@ -325,36 +334,11 @@ namespace Avalonia.Controls
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);
- }
+ UpdateVisualStateForCompactPaneLength(change.GetNewValue());
}
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;
+ UpdateVisualStateForDisplayMode(change.GetNewValue());
}
else if (change.Property == IsPaneOpenProperty)
{
@@ -389,10 +373,7 @@ namespace Avalonia.Controls
}
else if (change.Property == PanePlacementProperty)
{
- var oldState = GetPseudoClass(change.GetOldValue());
- var newState = GetPseudoClass(change.GetNewValue());
- PseudoClasses.Remove($":{oldState}");
- PseudoClasses.Add($":{newState}");
+ UpdateVisualStateForPanePlacementProperty(change.GetNewValue());
}
else if (change.Property == UseLightDismissOverlayModeProperty)
{
@@ -438,7 +419,7 @@ namespace Avalonia.Controls
e.Handled = true;
}
}
-
+
private bool ShouldClosePane()
{
return (DisplayMode == SplitViewDisplayMode.CompactOverlay || DisplayMode == SplitViewDisplayMode.Overlay);
@@ -471,14 +452,14 @@ namespace Avalonia.Controls
{
return mode switch
{
- SplitViewDisplayMode.Inline => "inline",
- SplitViewDisplayMode.CompactInline => "compactinline",
- SplitViewDisplayMode.Overlay => "overlay",
- SplitViewDisplayMode.CompactOverlay => "compactoverlay",
+ SplitViewDisplayMode.Inline => ":inline",
+ SplitViewDisplayMode.CompactInline => ":compactinline",
+ SplitViewDisplayMode.Overlay => ":overlay",
+ SplitViewDisplayMode.CompactOverlay => ":compactoverlay",
_ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null)
};
}
-
+
///
/// Gets the appropriate PseudoClass for the given .
///
@@ -486,8 +467,8 @@ namespace Avalonia.Controls
{
return placement switch
{
- SplitViewPanePlacement.Left => "left",
- SplitViewPanePlacement.Right => "right",
+ SplitViewPanePlacement.Left => ":left",
+ SplitViewPanePlacement.Right => ":right",
_ => throw new ArgumentOutOfRangeException(nameof(placement), placement, null)
};
}
@@ -519,6 +500,53 @@ namespace Avalonia.Controls
return value;
}
+ private void UpdateVisualStateForCompactPaneLength(double newLen)
+ {
+ 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);
+ }
+ }
+
+ private void UpdateVisualStateForDisplayMode(SplitViewDisplayMode newValue)
+ {
+ if (!string.IsNullOrEmpty(_lastDisplayModePseudoclass))
+ {
+ PseudoClasses.Remove(_lastDisplayModePseudoclass);
+ }
+
+ _lastDisplayModePseudoclass = GetPseudoClass(newValue);
+ PseudoClasses.Add(_lastDisplayModePseudoclass);
+
+ var (closedPaneWidth, paneColumnGridLength) = newValue 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 UpdateVisualStateForPanePlacementProperty(SplitViewPanePlacement newValue)
+ {
+ if (!string.IsNullOrEmpty(_lastPlacementPseudoclass))
+ {
+ PseudoClasses.Remove(_lastPlacementPseudoclass);
+ }
+
+ _lastPlacementPseudoclass = GetPseudoClass(newValue);
+ PseudoClasses.Add(_lastPlacementPseudoclass);
+ }
+
///
/// Coerces/validates the property value.
///