自定义 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 并指定格式,例如我意识到这个问题已经回答了很长时间了,但是直接绑定到 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 更改默认值“显示日历”