WinUI3: DatePicker control shows margin to left and right side

Viewed 70

I am using the DatePicker control of WinUI3.

Windows App SDK versions I tested with were 1.0.3 and 1.1.1.

I noticed that the DatePicker is sometimes displayed with something that seems to be a fixed margin to the left and the right side. This causes this control to be aligned differently to other controls that I have in this view.

Here is a screenshot that shows the problem. In order to show the margin, I added some kind of element in the background, so you can see the margin of the DatePicker in dark grey color. I also added two red arrows pointing to the respective area. (By the way, the screenshot was taking using "Dark Mode").

enter image description here


In my case the DatePicker is displayed in a column of a Grid and it should simply adapt to the widht of the Grid column.

Currently I have this code:

        <DatePicker Grid.Column="2" Orientation="Horizontal" MinWidth="200" HorizontalAlignment="Stretch"
                    Date="{x:Bind Path=ViewModel.MyDate, Mode=TwoWay}"/>

What I already tried is specifying a negative Margin for the DatePicker which had no effect. Also specifying a Padding of 0 had no effect.

Do you know a way to get rid of this margin? I would be nice to have a solution that does not require to completely rewrite the control template.

Thank you.



Update

I noticed that the problem seems to be related to the maximum width the DatePicker allows. It appears that it has a maximum widht of a little less than 500 units. If you try "to force" it to expand beyond this width, the undesired Margins begin to appear (see second Screenshot below).

Here is a complete example to reproduce it:

<Grid>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"></ColumnDefinition>  <!-- Column for Label -->
        <ColumnDefinition Width="20"></ColumnDefinition>    <!-- Margin -->
        <ColumnDefinition Width="500"></ColumnDefinition>   <!-- Column for content -->
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>

    <!-- Title row -->
    <TextBlock Grid.Row="0" Grid.Column="2" MinWidth="200" >Column that has 500 Width</TextBlock>

    <!-- First row with a TextBox control -->
    <TextBlock Grid.Row="1" Grid.Column="0" Text="Label for Textbox" VerticalAlignment="Center" Margin="0,0,20,0"></TextBlock>
    <TextBox Grid.Row="1" Grid.Column="2" MinWidth="200" ></TextBox>

    <!-- Second row with a DatePicker control -->
    <TextBlock Grid.Row="2" Grid.Column="0" Text="Label for DatePicker" VerticalAlignment="Center" Margin="0,0,20,0"></TextBlock>
    <DatePicker Grid.Row="2" Grid.Column="2" MinWidth="200"  HorizontalAlignment="Stretch"></DatePicker>

</Grid>

In the screenshot you can see that the TextBox control is able to expand to a width of 500, whereas the DatePicker is not.

enter image description here

1 Answers

There is a DatePickerThemeMaxWidth resource that constraints the maximum width of the Button in the DatePicker. There is also a DatePickerThemeMinWidth resource.

You could either create a custom template for the existing control or create your own custom control and override the OnApplyTemplate() method:

public class CustomDatePicker : DatePicker
{
    private Button _flyoutButton;

    public CustomDatePicker() => SizeChanged += OnSizeChanged;

    protected override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        _flyoutButton = GetTemplateChild("FlyoutButton") as Button;
        if (_flyoutButton != null)
        {
            // Note: The default value that gets overridden here for the MaxWidth is 456
            _flyoutButton.MinWidth = double.PositiveInfinity;
            _flyoutButton.MaxWidth = double.PositiveInfinity;
        }

    }

    private void OnSizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (_flyoutButton != null)
        {
            _flyoutButton.MinWidth = ActualWidth;
            _flyoutButton.MaxWidth = ActualWidth;
        }
    }
}

XAML:

<local:CustomDatePicker Grid.Row="2" Grid.Column="2" MinWidth="200" HorizontalAlignment="Stretch" />
Related