如何本地化 WPF 4.0 DatePicker 控件
Posted
技术标签:
【中文标题】如何本地化 WPF 4.0 DatePicker 控件【英文标题】:How to localize the WPF 4.0 DatePicker control 【发布时间】:2011-04-09 23:48:44 【问题描述】:当您清除新 WPF 4.0 DatePicker 控件上的框时,它会显示“选择日期”
有没有办法本地化文本?
【问题讨论】:
【参考方案1】:我采纳了马特的想法,并对其进行了一些扩展;我已经实现了一个附加行为,它允许您通过 XAML 为每个 DatePicker 控件定义水印。代码如下:
namespace DatePickerWatermark
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
public static class DatePickerWatermarkBehaviour
public static readonly DependencyProperty WatermarkProperty =
DependencyProperty.RegisterAttached(
"Watermark",
typeof(string),
typeof(DatePickerWatermarkBehaviour),
new UIPropertyMetadata(null, OnWatermarkChanged));
public static string GetWatermark(Control control)
return (string)control.GetValue(WatermarkProperty);
public static void SetWatermark(Control control, string value)
control.SetValue(WatermarkProperty, value);
private static void OnWatermarkChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
var datePicker = dependencyObject as DatePicker;
if (datePicker == null)
return;
if ((e.NewValue != null) && (e.OldValue == null))
datePicker.Loaded += DatePickerLoaded;
else if ((e.NewValue == null) && (e.OldValue != null))
datePicker.Loaded -= DatePickerLoaded;
private static void DatePickerLoaded(object sender, RoutedEventArgs e)
var datePicker = sender as DatePicker;
if (datePicker == null)
return;
var datePickerTextBox = GetFirstChildOfType<DatePickerTextBox>(datePicker);
if (datePickerTextBox == null)
return;
var partWatermark = datePickerTextBox.Template.FindName("PART_Watermark", datePickerTextBox) as ContentControl;
if (partWatermark == null)
return;
partWatermark.Content = GetWatermark(datePicker);
private static T GetFirstChildOfType<T>(DependencyObject dependencyObject) where T : DependencyObject
if (dependencyObject == null)
return null;
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
var child = VisualTreeHelper.GetChild(dependencyObject, i);
var result = (child as T) ?? GetFirstChildOfType<T>(child);
if (result != null)
return result;
return null;
这是一些 XAML 示例:
<Window x:Class="DatePickerWatermark.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:b="clr-namespace:DatePickerWatermark" Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.Resources>
<Style TargetType="DatePicker">
<Setter Property="Margin" Value="10,5"/>
</Style>
<Style x:Key="EnglishDatePicker" TargetType="DatePicker" BasedOn="StaticResource x:Type DatePicker">
<Setter Property="b:DatePickerWatermarkBehaviour.Watermark" Value="Please select a date:"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DatePicker Grid.Row="0" b:DatePickerWatermarkBehaviour.Watermark=""/>
<DatePicker Grid.Row="1" b:DatePickerWatermarkBehaviour.Watermark="Wählen Sie ein Datum"/>
<DatePicker Grid.Row="2" b:DatePickerWatermarkBehaviour.Watermark="Sélectionner une date"/>
<DatePicker Grid.Row="3" Style="StaticResource EnglishDatePicker"/>
<DatePicker Grid.Row="4" Style="StaticResource EnglishDatePicker"/>
</Grid>
</Window>
【讨论】:
【参考方案2】:以下是无需从 DatePicker 派生新控件的方法:
Customizing the WPF DatePicker's Watermark
【讨论】:
【参考方案3】:不幸的是,设置水印文字有点棘手。
如何做到这一点你可以在这篇文章中看到:Changing the watermark text in a DatePicker control
【讨论】:
有 WPF 方面的解决方案吗?【参考方案4】:Wayne,这很好用,但当 DatePicker 是 DataGridColumnHeader 的一部分时不起作用,有时当 DatePicker 处于先隐藏然后可见的控件上时。 Matt Hamilton 的解决方案仅适用于 onLoad,当您更改 selectedDate 时,再次出现烦人的 Select a date watermark。最简单的解决方案就是在自定义类中覆盖 OnRender 事件。如果您设置 watermark 属性而不是您需要覆盖 onload 事件的水印内容。完整的课程在这里:
public class myDateTimePicker : DatePicker
public string Watermark get; set;
protected override void OnSelectedDateChanged(SelectionChangedEventArgs e)
base.OnSelectedDateChanged(e);
//SetWatermark();
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
base.OnRender(drawingContext);
SetWatermark();
private void SetWatermark()
FieldInfo fiTextBox = typeof(DatePicker).GetField("_textBox", BindingFlags.Instance | BindingFlags.NonPublic);
if (fiTextBox != null)
DatePickerTextBox dateTextBox = (DatePickerTextBox)fiTextBox.GetValue(this);
if (dateTextBox != null)
if (string.IsNullOrWhiteSpace(this.Watermark))
this.Watermark = "Custom watermark";
// if you set property this way then you need to override OnSelectedDateChanged event
//PropertyInfo piWatermark = typeof(DatePickerTextBox).GetProperty("Watermark", BindingFlags.Instance | BindingFlags.NonPublic);
//if (piWatermark != null)
//
// piWatermark.SetValue(dateTextBox, this.Watermark, null);
//
var partWatermark = dateTextBox.Template.FindName("PART_Watermark", dateTextBox) as ContentControl;
if (partWatermark != null)
partWatermark.Foreground = new SolidColorBrush(Colors.Gray);
partWatermark.Content = this.Watermark;
【讨论】:
以上是关于如何本地化 WPF 4.0 DatePicker 控件的主要内容,如果未能解决你的问题,请参考以下文章
如何从 C# 中的 DatePicker(WPF) 中获取价值?
如何在 WPF 中将 DatePicker 添加到 DataGridTextColumn