UWP - DatePicker 和 TimePicker 自定义

UWP - DatePicker and TimePicker customization

我想在同一行(横向)上使用 DatePicker 和 TimePicker。我的问题是这些控件太宽了。所以我定制了它们以减少内容,但我无法减少宽度,因为弹出窗口太宽了。因此,我寻找一种方法来自定义弹出窗口或为控件和弹出窗口设置不同的大小。

这是我的 DatePicker 样式:

<Style TargetType="DatePicker">
    <Setter Property="Orientation" Value="Horizontal"/>
    <Setter Property="IsTabStop" Value="False"/>
    <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
    <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
    <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
    <Setter Property="HorizontalAlignment" Value="Left"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="DatePicker">
                <StackPanel x:Name="LayoutRoot" Margin="{TemplateBinding Padding}">
                    <StackPanel.Resources>
                        <Style x:Key="DatePickerFlyoutButtonStyle" TargetType="Button">
                            <Setter Property="UseSystemFocusVisuals" Value="False" />
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="Button">
                                        <Grid Background="{TemplateBinding Background}">
                                            <VisualStateManager.VisualStateGroups>
                                                <VisualStateGroup x:Name="CommonStates">
                                                    <VisualState x:Name="Normal" />
                                                    <VisualState x:Name="PointerOver">
                                                        <Storyboard>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                             Storyboard.TargetProperty="BorderBrush">
                                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumBrush}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                             Storyboard.TargetProperty="Background">
                                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlPageBackgroundAltMediumBrush}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                             Storyboard.TargetProperty="Foreground">
                                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                        </Storyboard>
                                                    </VisualState>
                                                    <VisualState x:Name="Pressed">
                                                        <Storyboard>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                             Storyboard.TargetProperty="Background">
                                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                             Storyboard.TargetProperty="BorderBrush">
                                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                             Storyboard.TargetProperty="Foreground">
                                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                        </Storyboard>
                                                    </VisualState>
                                                    <VisualState x:Name="Disabled">
                                                        <Storyboard>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                             Storyboard.TargetProperty="Background">
                                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                             Storyboard.TargetProperty="BorderBrush">
                                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                             Storyboard.TargetProperty="Foreground">
                                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                        </Storyboard>
                                                    </VisualState>
                                                </VisualStateGroup>
                                                <VisualStateGroup x:Name="FocusStates">
                                                    <VisualState x:Name="Focused">
                                                        <Storyboard>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                             Storyboard.TargetProperty="Background">
                                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListAccentLowBrush}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
                                                             Storyboard.TargetProperty="Foreground">
                                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
                                                            </ObjectAnimationUsingKeyFrames>
                                                        </Storyboard>
                                                    </VisualState>
                                                    <VisualState x:Name="Unfocused" />
                                                    <VisualState x:Name="PointerFocused" />
                                                </VisualStateGroup>
                                            </VisualStateManager.VisualStateGroups>
                                            <ContentPresenter x:Name="ContentPresenter"
                                    BorderBrush="{TemplateBinding BorderBrush}"
                                    Background="{ThemeResource SystemControlBackgroundAltMediumLowBrush}"
                                    BorderThickness="{TemplateBinding BorderThickness}"
                                    Content="{TemplateBinding Content}"
                                    Foreground="{TemplateBinding Foreground}"
                                    HorizontalContentAlignment="Stretch"
                                    VerticalContentAlignment="Stretch"
                                    AutomationProperties.AccessibilityView="Raw"/>
                                        </Grid>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </StackPanel.Resources>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter"
                                             Storyboard.TargetProperty="Foreground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FirstPickerSpacing"
                                             Storyboard.TargetProperty="Fill">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="SecondPickerSpacing"
                                             Storyboard.TargetProperty="Fill">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <ContentPresenter x:Name="HeaderContentPresenter"
                                      x:DeferLoadStrategy="Lazy"
                                      Visibility="Collapsed"
                                      Content="{TemplateBinding Header}"
                                      ContentTemplate="{TemplateBinding HeaderTemplate}"
                                      Margin="0,0,0,8"
                                      Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}"
                                      AutomationProperties.AccessibilityView="Raw"
                                      BorderBrush="{TemplateBinding BorderBrush}"/>
                    <Button x:Name="FlyoutButton"
                            Style="{StaticResource DatePickerFlyoutButtonStyle}"
                            Foreground="{TemplateBinding Foreground}"
                            Background="{TemplateBinding Background}"
                            IsEnabled="{TemplateBinding IsEnabled}"
                            HorizontalAlignment="Stretch"
                            HorizontalContentAlignment="Stretch"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid x:Name="FlyoutButtonContentGrid"
                              HorizontalAlignment="Center">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" x:Name="DayColumn" />
                                <ColumnDefinition Width="Auto" x:Name="FirstSpacerColumn" />
                                <ColumnDefinition Width="Auto" x:Name="MonthColumn" />
                                <ColumnDefinition Width="Auto" x:Name="SecondSpacerColumn" />
                                <ColumnDefinition Width="Auto" x:Name="YearColumn" />
                            </Grid.ColumnDefinitions>

                            <TextBlock x:Name="DayTextBlock" Text="Day" TextAlignment="Center" Margin="4" FontFamily="{TemplateBinding FontFamily}" FontWeight="{TemplateBinding FontWeight}" FontSize="{TemplateBinding FontSize}" AutomationProperties.AccessibilityView="Raw"/>
                            <TextBlock x:Name="MonthTextBlock" Text="Month" TextAlignment="Left" Margin="4" FontFamily="{TemplateBinding FontFamily}" FontWeight="{TemplateBinding FontWeight}" FontSize="{TemplateBinding FontSize}" AutomationProperties.AccessibilityView="Raw"/>
                            <TextBlock x:Name="YearTextBlock" Text="Year" TextAlignment="Center" Margin="4" FontFamily="{TemplateBinding FontFamily}" FontWeight="{TemplateBinding FontWeight}" FontSize="{TemplateBinding FontSize}" AutomationProperties.AccessibilityView="Raw"/>

                        </Grid>
                    </Button>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

要自定义弹出窗口,我们可以编辑 DatePickerFlyoutPresenter and TimePickerFlyoutPresenter 的样式和模板。我们可以在 generic.xaml 中找到这些样式,这些样式位于 \(Program Files)\Windows Kits\DesignTime\CommonConfiguration\Neutral\UAP.0.14393 .0\Generic 来自 Windows SDK 安装的文件夹。不同的SDK版本,路径不同,样式和资源可能有不同的取值。使用14393中DatePickerFlyoutPresenter的默认样式 例如:

<!-- Default style for Windows.UI.Xaml.Controls.DatePickerFlyoutPresenter -->
<Style TargetType="DatePickerFlyoutPresenter">
    <Setter Property="Width" Value="296" />
    <Setter Property="MinWidth" Value="296" />
    <Setter Property="MaxHeight" Value="398" />
    <Setter Property="IsTabStop" Value="False" />
    <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
    <Setter Property="FontWeight" Value="Normal" />
    <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
    <Setter Property="Background" Value="{ThemeResource DatePickerFlyoutPresenterBackground}" />
    <Setter Property="AutomationProperties.AutomationId" Value="DatePickerFlyoutPresenter" />
    <Setter Property="BorderBrush" Value="{ThemeResource DatePickerFlyoutPresenterBorderBrush}" />
    <Setter Property="BorderThickness" Value="{ThemeResource DateTimeFlyoutBorderThickness}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="DatePickerFlyoutPresenter">
                <Border x:Name="Background"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    MaxHeight="398">
                    <Grid x:Name="ContentPanel">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Grid x:Name="PickerHostGrid">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="78*" x:Name="DayColumn" />
                                <ColumnDefinition Width="Auto" x:Name="FirstSpacerColumn" />
                                <ColumnDefinition Width="132*" x:Name="MonthColumn" />
                                <ColumnDefinition Width="Auto" x:Name="SecondSpacerColumn" />
                                <ColumnDefinition Width="78*" x:Name="YearColumn" />
                            </Grid.ColumnDefinitions>
                            <Rectangle x:Name="HighlightRect"
                                Fill="{ThemeResource DatePickerFlyoutPresenterHighlightFill}"
                                Grid.Column="0"
                                Grid.ColumnSpan="5"
                                VerticalAlignment="Center"
                                Height="44" />
                            <Rectangle x:Name="FirstPickerSpacing"
                                Fill="{ThemeResource DatePickerFlyoutPresenterSpacerFill}"
                                HorizontalAlignment="Center"
                                Width="2"
                                Grid.Column="1" />
                            <Rectangle x:Name="SecondPickerSpacing"
                                Fill="{ThemeResource DatePickerFlyoutPresenterSpacerFill}"
                                HorizontalAlignment="Center"
                                Width="2"
                                Grid.Column="3" />
                        </Grid>
                        <Grid Grid.Row="1" Height="45" x:Name="AcceptDismissHostGrid">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <Rectangle Height="2"
                                VerticalAlignment="Top"
                                Fill="{ThemeResource DatePickerFlyoutPresenterSpacerFill}"
                                Grid.ColumnSpan="2" />
                            <Button x:Name="AcceptButton"
                                Grid.Column="0"
                                Content="&#xE8FB;"
                                FontFamily="{ThemeResource SymbolThemeFontFamily}"
                                FontSize="16"
                                HorizontalAlignment="Stretch"
                                VerticalAlignment="Stretch"
                                Style="{StaticResource DateTimePickerFlyoutButtonStyle}"
                                Margin="0,2,0,0" />
                            <Button x:Name="DismissButton"
                                Grid.Column="1"
                                Content="&#xE711;"
                                FontFamily="{ThemeResource SymbolThemeFontFamily}"
                                FontSize="16"
                                HorizontalAlignment="Stretch"
                                VerticalAlignment="Stretch"
                                Style="{StaticResource DateTimePickerFlyoutButtonStyle}"
                                Margin="0,2,0,0" />
                        </Grid>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我们可以改变Grid.ColumnDefinitions来减少宽度。

但请注意,虽然DatePickerFlyoutPresenter中有WidthMinWidth属性,但更改它们没有任何效果。 DatePickerFlyoutPresenter的宽度由DatePicker决定。它们具有相同的宽度。如果我们更改 DatePicker 的宽度,弹出窗口将自动调整其宽度。

此外,在DatePickerFlyoutPresenter中,我们无法像您在DatePicker的样式中那样将ColumnDefinition的宽度更改为Auto。因为在DatePickerFlyoutPresenter、"DayColumn"、"MonthColumn"和"YearColumn"里面填充了LoopingSelector, which uses a panel like Canvas。如果我们将列的宽度设置为 AutoLoopingSelector 的宽度将为零,用户将看不到任何内容。

所以我们可以自定义的东西可能不多,我们最好为 DatePicker 设置一个固定的宽度,如下所示,以确保用户可以在选择器或选择器的弹出窗口中看到完整的元素.

<DatePicker Width="200" MinWidth="0" />

时间选择器和日期选择器一样。如果您想要更大的灵活性,我建议您使用新的自定义控件。这是一篇关于 DatePicker calendar custom control for WinRT Xaml. You can refer to the blog and the source code on Codeplex 实现您自己的博客。

为了将自定义样式更改应用于 DatePicker 和 TimePicker 的 DatePickerFlyoutPresenter,应将自定义的 DatePickerFlyoutPresenter 样式应用为应用程序级别。我的意思是,自定义更改应该出现在 (App.xaml) 中,因为 DatePickerFlyoutPresenter 是应用程序级弹出窗口。如果应用于页面级别或控件级别,则不会生效。