From 9b5437bb5a29974eba34305fedca90572e17f0dd Mon Sep 17 00:00:00 2001 From: JoaoCruz Date: Wed, 19 Aug 2026 15:11:41 +0000 Subject: [PATCH] Implement VerticalContentAlignment for DatePicker and TimePicker (#21464) * Add VerticalContentAlignment property to DatePicker and TimePicker This change registers VerticalContentAlignmentProperty as a StyledProperty using ContentControl's property as the owner for both DatePicker and TimePicker controls to maintain framework consistency. Basic xUnit v3 unit tests are introduced to validate property round-trips (Top, Center, Bottom, Stretch) and to ensure the default value correctly resolves to Stretch. This establishes the necessary C# infrastructure before modifying the control templates. Part of #21211: implment fluent theme layout * Fix VerticalContentAlignment bindings and integration tests - Bind internal grids to VerticalContentAlignment in Fluent and Simple themes for DatePicker and TimePicker controls. - Add comprehensive integration tests using mocked NameScopes in DatePickerTests and TimePickerTests to verify visual propagation. - Validate visual layout correctness using the ControlCatalog app. Closes AvaloniaUI#21211 * Remove tautological tests --------- Co-authored-by: Martim Claudino Co-authored-by: Julien Lebosquain --- .../DateTimePickers/DatePicker.cs | 15 +++++++++++++++ .../DateTimePickers/TimePicker.cs | 14 ++++++++++++++ .../Controls/DatePicker.xaml | 2 +- .../Controls/TimePicker.xaml | 2 +- .../Controls/DatePicker.xaml | 3 ++- .../Controls/TimePicker.xaml | 2 +- .../DatePickerTests.cs | 19 +++++++++++++++++++ .../TimePickerTests.cs | 19 +++++++++++++++++++ 8 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs index 2f406252f7..c4206c7315 100644 --- a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs +++ b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs @@ -75,6 +75,21 @@ namespace Avalonia.Controls public static readonly StyledProperty YearVisibleProperty = AvaloniaProperty.Register(nameof(YearVisible), true); + /// + /// Defines the property. + /// + public static readonly StyledProperty VerticalContentAlignmentProperty = + ContentControl.VerticalContentAlignmentProperty.AddOwner(); + + /// + /// Gets or sets the vertical alignment of the content within the control. + /// + public VerticalAlignment VerticalContentAlignment + { + get => GetValue(VerticalContentAlignmentProperty); + set => SetValue(VerticalContentAlignmentProperty, value); + } + /// /// Defines the Property /// diff --git a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs index 95d9e82782..7c6f96247f 100644 --- a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs +++ b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs @@ -50,6 +50,20 @@ namespace Avalonia.Controls public static readonly StyledProperty ClockIdentifierProperty = AvaloniaProperty.Register(nameof(ClockIdentifier), "12HourClock", coerce: CoerceClockIdentifier); + /// + /// Defines the property. + /// + public static readonly StyledProperty VerticalContentAlignmentProperty = + ContentControl.VerticalContentAlignmentProperty.AddOwner(); + + /// + /// Gets or sets the vertical alignment of the content within the control. + /// + public VerticalAlignment VerticalContentAlignment + { + get => GetValue(VerticalContentAlignmentProperty); + set => SetValue(VerticalContentAlignmentProperty, value); + } /// /// Defines the property /// diff --git a/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml index b38187cd60..d7bb32fb43 100644 --- a/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml @@ -98,7 +98,7 @@ HorizontalAlignment="Stretch" VerticalAlignment="Stretch" TemplatedControl.IsTemplateFocusTarget="True"> - + - + + ColumnDefinitions="78*,Auto,132*,Auto,78*" + VerticalAlignment="{TemplateBinding VerticalContentAlignment}"> - + diff --git a/tests/Avalonia.Controls.UnitTests/TimePickerTests.cs b/tests/Avalonia.Controls.UnitTests/TimePickerTests.cs index 11c52392f1..86e77f9722 100644 --- a/tests/Avalonia.Controls.UnitTests/TimePickerTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TimePickerTests.cs @@ -11,6 +11,7 @@ using Avalonia.Platform; using Avalonia.Threading; using Avalonia.UnitTests; using Avalonia.VisualTree; +using Avalonia.Layout; using Moq; using Xunit; @@ -466,5 +467,23 @@ namespace Avalonia.Controls.UnitTests return contentPanel; }); } + + [Theory] + [InlineData(Avalonia.Layout.VerticalAlignment.Top)] + [InlineData(Avalonia.Layout.VerticalAlignment.Center)] + [InlineData(Avalonia.Layout.VerticalAlignment.Bottom)] + [InlineData(Avalonia.Layout.VerticalAlignment.Stretch)] + public void VerticalContentAlignment_RoundTrips(Avalonia.Layout.VerticalAlignment value) + { + var timePicker = new TimePicker { VerticalContentAlignment = value }; + Assert.Equal(value, timePicker.VerticalContentAlignment); + } + + [Fact] + public void VerticalContentAlignment_Default_Is_Stretch() + { + var timePicker = new TimePicker(); + Assert.Equal(Avalonia.Layout.VerticalAlignment.Stretch, timePicker.VerticalContentAlignment); + } } }