自定义 WPF DatePickerTextBox 模板

Posted

技术标签:

【中文标题】自定义 WPF DatePickerTextBox 模板【英文标题】:Custom WPF DatePickerTextBox Template 【发布时间】:2011-04-07 20:53:09 【问题描述】:

我正在尝试在DatePicker 控件中使用自定义TextBox,但我无法将弹出日历中的日期绑定到TextBox。我不想对整个DatePicker 进行样式化,除非我必须这样做,而且DatePickerTextBox 有自己的控制,所以必须有一种方法来只改变它。下面的代码是我的开始:

<Style TargetType="x:Type DatePickerTextBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="x:Type DatePickerTextBox">
                <TextBox x:Name="PART_TextBox" Text="Binding Path=SelectedDate" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我可能没有正确进行绑定,或者PART_TextBox 可能不正确,因为它不是DatePicker 模板本身的一部分。

请有人帮忙! :)

提前致谢!

【问题讨论】:

【参考方案1】:

试试这个:

<DatePicker>
    <DatePicker.Resources>
        <Style TargetType="x:Type DatePickerTextBox">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate>
                        <TextBox x:Name="PART_TextBox" 
                                    Text="Binding Path=SelectedDate, RelativeSource=RelativeSource AncestorType=x:Type DatePicker" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DatePicker.Resources>
</DatePicker>

【讨论】:

明白了。非常感谢! 我有一个问题:它不支持默认模板所做的短/长日期格式。 @dex3707 您可以将 StringFormat 添加到 Textbinding 并指定格式,例如【参考方案2】:

我意识到这个问题已经回答了很长时间了,但是直接绑定到 DatePicker 的 Text 属性将允许您的控件模板中的 TextBox 轻松实现由 @987654323 提供的短/长格式@。

<DatePicker>
    <DatePicker.Resources>
        <Style TargetType="x:Type DatePickerTextBox">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <TextBox Text="Binding Text, RelativeSource=RelativeSource AncestorType=x:Type DatePicker" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DatePicker.Resources>
</DatePicker>

“PART_TextBox”也不是必需的,因为它不是DatePickerTextBox 模板的一部分。 DatePickerTextBox 包含的唯一 PART 是:

[TemplatePart(Name = DatePickerTextBox.ElementContentName, Type = typeof(ContentControl))]
public sealed partial class DatePickerTextBox : TextBox

private const string ElementContentName = "PART_Watermark";

并继承自TextBoxBase...

[TemplatePart(Name = "PART_ContentHost", Type = typeof(FrameworkElement))] 
public abstract class TextBoxBase : Control

internal const string ContentHostTemplateName = "PART_ContentHost";

替代解决方案: 如果您选择不使用 TextBox 并使用继承的 PART,您将能够更改 DatePickerTextBox 而无需更改控件的默认功能。

<DatePicker>
    <DatePicker.Resources>
        <Style TargetType="x:Type DatePickerTextBox">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Grid SnapsToDevicePixels="TemplateBinding SnapsToDevicePixels">
                            <Border BorderThickness="TemplateBinding BorderThickness"
                                    BorderBrush="TemplateBinding BorderBrush"
                                    Background="TemplateBinding Background"/>

                            <ScrollViewer Name="PART_ContentHost"
                                          HorizontalAlignment="TemplateBinding HorizontalContentAlignment"
                                          VerticalAlignment="TemplateBinding VerticalContentAlignment"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DatePicker.Resources>
</DatePicker>

【讨论】:

我已经在这上面花费了几个小时,然后我发现你的答案隐藏在大量的问题和答案中。你的是最好的实现。好东西!【参考方案3】:

如果您在 XAML (1) 中声明一个元素,然后在 Design 视图中查看它,您可以右键单击 (2) 并导出其模板 (3):

1

<Window ...attributes...>
    <Grid>
        <DatePickerTextBox />
    </Grid>
</Window>

2

3

<Style x:Key="DatePickerTextBoxStyle1" TargetType="x:Type DatePickerTextBox">
    <Setter Property="Foreground" Value="DynamicResource x:Static SystemColors.WindowTextBrushKey"/>
    <Setter Property="Background" Value="DynamicResource x:Static SystemColors.WindowBrushKey"/>
    <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
    <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="x:Type DatePickerTextBox">
                <Grid>
                    <Grid.Resources>
                        <SolidColorBrush x:Key="WatermarkBrush" Color="#FFAAAAAA"/>
                    </Grid.Resources>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition GeneratedDuration="0"/>
                                <VisualTransition GeneratedDuration="0:0:0.1" To="MouseOver"/>
                            </VisualStateGroup.Transitions>
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <ColorAnimation Duration="0" To="#FF99C1E2" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="ContentElement"/>
                                    <ColorAnimation Duration="0" To="#FF99C1E2" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="watermark_decorator"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="WatermarkStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition GeneratedDuration="0"/>
                            </VisualStateGroup.Transitions>
                            <VisualState x:Name="Unwatermarked"/>
                            <VisualState x:Name="Watermarked">
                                <Storyboard>
                                    <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentElement"/>
                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Watermark"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="FocusStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition GeneratedDuration="0"/>
                            </VisualStateGroup.Transitions>
                            <VisualState x:Name="Unfocused"/>
                            <VisualState x:Name="Focused">
                                <Storyboard>
                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisual"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border x:Name="Border" BorderBrush="TemplateBinding BorderBrush" BorderThickness="TemplateBinding BorderThickness" Background="TemplateBinding Background" CornerRadius="1" Opacity="1" Padding="TemplateBinding Padding">
                        <Grid x:Name="WatermarkContent" HorizontalAlignment="TemplateBinding HorizontalContentAlignment" VerticalAlignment="TemplateBinding VerticalContentAlignment">
                            <Border x:Name="ContentElement" BorderBrush="#FFFFFFFF" BorderThickness="1"/>
                            <Border x:Name="watermark_decorator" BorderBrush="#FFFFFFFF" BorderThickness="1">
                                <ContentControl x:Name="PART_Watermark" Focusable="False" IsHitTestVisible="False" Opacity="0" Padding="2"/>
                            </Border>
                            <ScrollViewer x:Name="PART_ContentHost" HorizontalContentAlignment="TemplateBinding HorizontalContentAlignment" Margin="0" VerticalContentAlignment="TemplateBinding VerticalContentAlignment"/>
                            <Border x:Name="FocusVisual" BorderBrush="#FF45D6FA" CornerRadius="1" IsHitTestVisible="False" Opacity="0"/>
                        </Grid>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

【讨论】:

感谢您提供的超级有用的提示:D。

以上是关于自定义 WPF DatePickerTextBox 模板的主要内容,如果未能解决你的问题,请参考以下文章

将 WPFToolkit DatePickerTextBox 控件重写为自定义组合框控件

WPF 工具包 DatePicker 更改默认值“显示日历”

如何使用 Expression Blend 在 WPF 中编辑 DatePicker 的水印

wpf怎么自定义窗口

wpf DataGrid自定义相关问题

wpf 自定义控件的自定义属性的数据绑定问题