WPF DatePicker水印使用错误的语言,但日期格式正确

本文关键字:日期 格式 语言 DatePicker 错误 WPF | 更新日期: 2023-09-27 18:29:56

我有一个非常奇怪的问题:

在我的机器上,DatePicker根据我想要设置的语言/区域性更改其水印和日期格式。

如果我将我的应用程序复制到其他计算机,会发生以下情况:

在某台电脑上,它的工作原理就像在我的电脑上一样。在其他计算机上,只有日期格式会更改,但水印不会!不用说,有一个日期选择器,例如一个德国日期,但有一个英国水印,这是非常丑陋的。

这种行为的原因是什么

对于i18n,我使用以下代码:

App.xaml.cs:

public partial class App : Application
{
    public App()
    {
        CultureInfo ci = new CultureInfo("de-DE"); 
        Thread.CurrentThread.CurrentCulture = ci;
        Thread.CurrentThread.CurrentUICulture = ci;
    }
}

WindowMain.xaml.cs:

public partial class WindowMain : RibbonWindow
{
    public WindowMain()
    {
        this.Language = XmlLanguage.GetLanguage("de-DE");
        this.InitializeComponent();
    }
}

WPF DatePicker水印使用错误的语言,但日期格式正确

设置带水印的文本实际上很容易:

<DatePicker>
  <DatePicker.Resources>
    <Style TargetType="DatePickerTextBox">
      <Setter Property="Text" Value="Watermark Text"/>
    </Style>
  </DatePicker.Resources>
</DatePicker>

http://www.admindiaries.com/change-datepicker-watermark-in-wpf/

有一点我可以说,WatermarkDatePicker中实现了bug,没有容易访问的地方。也许,正是由于这种困难,文本的本地化不起作用。@Matt Hamilton有一篇精彩的文章,引用自这里:

不过,很多人(包括我自己)不喜欢DatePicker的一点是,默认情况下,如果没有显示日期,它会显示文本"选择日期"作为水印,并且该文本会被烘焙到控件中-它不本地化,也不可由任何公共属性访问。如果有问题的日期是可选的,并且您不一定想提示用户选择一个,那么这尤其令人沮丧。

在同一篇文章中,他提供了如何访问Watermark的决定。此处:

如何本地化WPF4.0 DatePicker控件

@Wayne Maurer附加依赖属性的形式创建了一个通用解决方案:

<DatePicker Grid.Row="2" 
            local:DatePickerWatermarkBehaviour.Watermark="Select the date" />

您需要基于当前的区域性,设置水印的文本,例如使用上面的示例。

Note:在Silverlight中到WatermarkDatePicker中进行访问[link]:

DatePickerTextBox box = base.GetTemplateChild("TextBox") as DatePickerTextBox;
box.Watermark = "Type or select a date --> "; 

Wayne解决方案运行良好,但当DatePicker是DataGridColumnHeader的一部分时,有时当DatePickr处于先隐藏后可见的控件上时,它不起作用。Matt Hamilton的解决方案仅适用于Load,当您更改selectedDate时,会再次出现令人讨厌的Select a date水印。最简单的解决方案就是覆盖自定义类中的OnRender事件。如果您设置了水印属性,而不是需要覆盖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;
                }
            }
        }
    }
}