From 771d32e5a51cc051dd8db31ec03f4e266d013f4f Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 15 Sep 2025 15:30:39 +0100 Subject: [PATCH] Add SplitViewPanePlacement settings for Top and Bottom. (#19465) * add SplitViewPanePlacement settings for Top and Bottom. * remove duplicated styles. * add missing transparent fills of lightdismiss area. * add simple theme support for splitview pane placement top/bottom. --- .../ControlCatalog/Pages/SplitViewPage.xaml | 9 +- .../ViewModels/SplitViewPageViewModel.cs | 18 +- src/Avalonia.Controls/SplitView/SplitView.cs | 24 +- .../SplitView/SplitViewPanePlacement.cs | 12 +- .../SplitView/SplitViewTemplateSettings.cs | 23 ++ .../Controls/SplitView.xaml | 284 +++++++++++++++--- .../Controls/SplitView.xaml | 229 +++++++++++++- 7 files changed, 540 insertions(+), 59 deletions(-) diff --git a/samples/ControlCatalog/Pages/SplitViewPage.xaml b/samples/ControlCatalog/Pages/SplitViewPage.xaml index 2edd895349..201765ad88 100644 --- a/samples/ControlCatalog/Pages/SplitViewPage.xaml +++ b/samples/ControlCatalog/Pages/SplitViewPage.xaml @@ -20,7 +20,13 @@ Content="UseLightDismissOverlayMode" IsChecked="{Binding UseLightDismissOverlayMode, ElementName=SplitView}" /> - + + Left + Right + Top + Bottom + + @@ -52,6 +58,7 @@ BorderThickness="1"> _isLeft; + get => _placement; set { - this.RaiseAndSetIfChanged(ref _isLeft, value); + this.RaiseAndSetIfChanged(ref _placement, value); this.RaisePropertyChanged(nameof(PanePlacement)); } } @@ -29,7 +29,15 @@ namespace ControlCatalog.ViewModels } } - public SplitViewPanePlacement PanePlacement => _isLeft ? SplitViewPanePlacement.Left : SplitViewPanePlacement.Right; + public SplitViewPanePlacement PanePlacement => + _placement switch + { + 0 => SplitViewPanePlacement.Left, + 1 => SplitViewPanePlacement.Right, + 2 => SplitViewPanePlacement.Top, + 3 => SplitViewPanePlacement.Bottom, + _ => SplitViewPanePlacement.Left + }; public SplitViewDisplayMode CurrentDisplayMode { diff --git a/src/Avalonia.Controls/SplitView/SplitView.cs b/src/Avalonia.Controls/SplitView/SplitView.cs index f78ac6e0ee..14054d183f 100644 --- a/src/Avalonia.Controls/SplitView/SplitView.cs +++ b/src/Avalonia.Controls/SplitView/SplitView.cs @@ -18,7 +18,7 @@ namespace Avalonia.Controls [TemplatePart("PART_PaneRoot", typeof(Panel))] [PseudoClasses(pcOpen, pcClosed)] [PseudoClasses(pcCompactOverlay, pcCompactInline, pcOverlay, pcInline)] - [PseudoClasses(pcLeft, pcRight)] + [PseudoClasses(pcLeft, pcRight, pcTop, pcBottom)] [PseudoClasses(pcLightDismiss)] public class SplitView : ContentControl { @@ -30,6 +30,8 @@ namespace Avalonia.Controls private const string pcInline = ":inline"; private const string pcLeft = ":left"; private const string pcRight = ":right"; + private const string pcTop = ":top"; + private const string pcBottom = ":bottom"; private const string pcLightDismiss = ":lightDismiss"; /// @@ -464,6 +466,8 @@ namespace Avalonia.Controls { SplitViewPanePlacement.Left => pcLeft, SplitViewPanePlacement.Right => pcRight, + SplitViewPanePlacement.Top => pcTop, + SplitViewPanePlacement.Bottom => pcBottom, _ => throw new ArgumentOutOfRangeException(nameof(placement), placement, null) }; } @@ -501,11 +505,14 @@ namespace Avalonia.Controls if (displayMode == SplitViewDisplayMode.CompactInline) { TemplateSettings.ClosedPaneWidth = newLen; + TemplateSettings.ClosedPaneHeight = newLen; } else if (displayMode == SplitViewDisplayMode.CompactOverlay) { TemplateSettings.ClosedPaneWidth = newLen; TemplateSettings.PaneColumnGridLength = new GridLength(newLen, GridUnitType.Pixel); + TemplateSettings.ClosedPaneHeight = newLen; + TemplateSettings.PaneRowGridLength = new GridLength(newLen, GridUnitType.Pixel); } } @@ -521,14 +528,25 @@ namespace Avalonia.Controls var (closedPaneWidth, paneColumnGridLength) = newValue switch { - SplitViewDisplayMode.Overlay => (0, new GridLength(0, GridUnitType.Pixel)), + SplitViewDisplayMode.Overlay => (0d, new GridLength(0, GridUnitType.Pixel)), SplitViewDisplayMode.CompactOverlay => (CompactPaneLength, new GridLength(CompactPaneLength, GridUnitType.Pixel)), - SplitViewDisplayMode.Inline => (0, new GridLength(0, GridUnitType.Auto)), + SplitViewDisplayMode.Inline => (0d, new GridLength(0, GridUnitType.Auto)), SplitViewDisplayMode.CompactInline => (CompactPaneLength, new GridLength(0, GridUnitType.Auto)), _ => throw new NotImplementedException(), }; TemplateSettings.ClosedPaneWidth = closedPaneWidth; TemplateSettings.PaneColumnGridLength = paneColumnGridLength; + + var (closedPaneHeight, paneRowGridLength) = newValue switch + { + SplitViewDisplayMode.Overlay => (0d, new GridLength(0, GridUnitType.Pixel)), + SplitViewDisplayMode.CompactOverlay => (CompactPaneLength, new GridLength(CompactPaneLength, GridUnitType.Pixel)), + SplitViewDisplayMode.Inline => (0d, new GridLength(0, GridUnitType.Auto)), + SplitViewDisplayMode.CompactInline => (CompactPaneLength, new GridLength(0, GridUnitType.Auto)), + _ => throw new NotImplementedException(), + }; + TemplateSettings.ClosedPaneHeight = closedPaneHeight; + TemplateSettings.PaneRowGridLength = paneRowGridLength; InvalidateLightDismissSubscription(); } diff --git a/src/Avalonia.Controls/SplitView/SplitViewPanePlacement.cs b/src/Avalonia.Controls/SplitView/SplitViewPanePlacement.cs index 62c5387192..f51267f636 100644 --- a/src/Avalonia.Controls/SplitView/SplitViewPanePlacement.cs +++ b/src/Avalonia.Controls/SplitView/SplitViewPanePlacement.cs @@ -13,6 +13,16 @@ /// /// The pane is shown to the right of content. /// - Right + Right, + + /// + /// The pane is shown above the content. + /// + Top, + + /// + /// The pane is shown below the content. + /// + Bottom } } diff --git a/src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs b/src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs index 1794b9260f..f4f8301c6e 100644 --- a/src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs +++ b/src/Avalonia.Controls/SplitView/SplitViewTemplateSettings.cs @@ -19,6 +19,15 @@ AvaloniaProperty.Register( nameof(PaneColumnGridLength)); + public static readonly StyledProperty ClosedPaneHeightProperty = + AvaloniaProperty.Register(nameof(ClosedPaneHeight), + 0d); + + public static readonly StyledProperty PaneRowGridLengthProperty = + AvaloniaProperty.Register( + nameof(PaneRowGridLength)); + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1032", Justification = "This property is supposed to be a styled readonly property.")] public double ClosedPaneWidth { @@ -32,5 +41,19 @@ get => GetValue(PaneColumnGridLengthProperty); internal set => SetValue(PaneColumnGridLengthProperty, value); } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1032", Justification = "This property is supposed to be a styled readonly property.")] + public double ClosedPaneHeight + { + get => GetValue(ClosedPaneHeightProperty); + internal set => SetValue(ClosedPaneHeightProperty, value); + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1032", Justification = "This property is supposed to be a styled readonly property.")] + public GridLength PaneRowGridLength + { + get => GetValue(PaneRowGridLengthProperty); + internal set => SetValue(PaneRowGridLengthProperty, value); + } } } diff --git a/src/Avalonia.Themes.Fluent/Controls/SplitView.xaml b/src/Avalonia.Themes.Fluent/Controls/SplitView.xaml index 6c5587f755..b90ec96b94 100644 --- a/src/Avalonia.Themes.Fluent/Controls/SplitView.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/SplitView.xaml @@ -51,7 +51,7 @@ HorizontalAlignment="Right" /> - + @@ -135,11 +135,11 @@ Width="1" HorizontalAlignment="Left" /> - + - + @@ -195,48 +195,254 @@ - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Avalonia.Themes.Simple/Controls/SplitView.xaml b/src/Avalonia.Themes.Simple/Controls/SplitView.xaml index 1b01e7dbe2..d23f230dc6 100644 --- a/src/Avalonia.Themes.Simple/Controls/SplitView.xaml +++ b/src/Avalonia.Themes.Simple/Controls/SplitView.xaml @@ -52,7 +52,7 @@ HorizontalAlignment="Right" /> - + @@ -135,7 +135,7 @@ Width="1" HorizontalAlignment="Left" /> - + @@ -194,8 +194,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + +