WPF DatePicker Watermark 使用了错误的语言,但 Dateformat 是正确的

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18589429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:34:12  来源:igfitidea点击:

WPF DatePicker Watermark uses wrong Language, but the Dateformat is correct

c#wpfinternationalizationdatepicker

提问by M C

I have a very strange Problem:

我有一个很奇怪的问题:

On my machine the DatePicker changes its watermark AND date-format according to the language/culture i want to set.

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

If i copy my application to other computers following happens:

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

On some computer it works like it does on my machine. On other computers only the date-format changes but the watermark does not! Needless to say it is very ugly to have a datepicker with e.g. a german date but an english watermark.

在某些计算机上,它的工作方式与在我的机器上一样。在其他计算机上,只有日期格式会发生变化,而水印不会!毋庸置疑,拥有带有例如德国日期但英文水印的日期选择器是非常丑陋的。

What is the cause for that behaviour?

这种行为的原因是什么?

For i18n i use following code:

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

App.xaml.cs:

应用程序.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:

WindowMain.xaml.cs:

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

采纳答案by Anatoliy Nikolaev

One thing I can say, Watermarkin DatePickerimplemented buggy, there is no easy access. Perhaps, because of this difficulty, the localization of the text does not work. There is a wonderful article of @Matt Hamilton, quote from here:

我可以说的一件事是,Watermark在已DatePicker实现的错误中,没有简单的访问。也许,因为这个困难,文本的本地化不起作用。有一篇精彩的文章@Matt Hamilton,引自这里

Something that a lot of people (myself included) don't like about the DatePicker, though, is that by default if no date is displayed it shows the text "Select a date" as a watermark, and this text is baked into the control - it's not localized or accessible by any public property. This is particularly frustrating if the date in question is optional and you don't necessarily want to prompt your users to select one.

但是,很多人(包括我自己)不喜欢 DatePicker 的一点是,默认情况下,如果没有显示日期,它会将文本“选择日期”显示为水印,并且此文本会被烘焙到控件中- 它没有被任何公共财产本地化或访问。如果所讨论的日期是可选的,并且您不一定希望提示用户选择一个日期,那么这尤其令人沮丧。

In the same article, he provide the decision of how to access to Watermark. Here:

在同一篇文章中,他提供了如何访问Watermark. 这里:

How to localize the WPF 4.0 DatePicker control

如何本地化 WPF 4.0 DatePicker 控件

@Wayne Maurercreated a universal solution in the form of attacheddependency property:

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

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

You need to be based on the current culture, set the text for watermarks, e.g. using above example.

您需要根据当前的文化,设置水印的文本,例如使用上面的示例。

Note:In Silverlight to Watermarkin DatePickermade access [link]:

Note:在 SilverlightWatermarkDatePicker访问 [ link]:

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

回答by Jón Arnar

It's actually really easy to set the watermarked text:

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

<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/

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

回答by Mario Rancic

Wayne solution works great but does not work when DatePicker is part of DataGridColumnHeader and sometimes when DatePicker is on control that is first hidden and then visible. Matt Hamilton's solution works only onLoad, and when you change selectedDate there is again annoying Select a date watermark. The easiest solution is just to override OnRender event in custom class. If you set watermark property and not a watermark content that you need to override onload event as well. Complete class is here:

Wayne 解决方案效果很好,但当 DatePicker 是 DataGridColumnHeader 的一部分时不起作用,有时当 DatePicker 处于先隐藏然后可见的控件时。马特汉密尔顿的解决方案仅适用于加载,当您更改 selectedDate 时,再次烦人的选择日期水印。最简单的解决方案是在自定义类中覆盖 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;
                }
            }
        }
    }

}