Wpf中的StringFormat本地化问题

时间:2009-02-06 12:28:27

标签: wpf datetime localization

在WPF 3.5SP1中,我使用DataBindings中的最后一个功能StringFormat:

 <TextBlock Text="{Binding Path=Model.SelectedNoteBook.OriginalDate, StringFormat='f'}"
                                   FontSize="20"
                                   TextTrimming="CharacterEllipsis" />

我面临的问题是日期总是用英语格式化......虽然我的系统是法语的?如何强制日期遵循系统日期?

10 个答案:

答案 0 :(得分:198)

// Ensure the current culture passed into bindings is the OS culture.
// By default, WPF uses en-US as the culture, regardless of the system settings.
FrameworkElement.LanguageProperty.OverrideMetadata(
      typeof(FrameworkElement),
      new FrameworkPropertyMetadata(
          XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

来自Creating an Internationalized Wizard in WPF

答案 1 :(得分:81)

定义以下xml命名空间:

xmlns:gl="clr-namespace:System.Globalization;assembly=mscorlib"

现在看到这个奇妙的解决方案:

<TextBlock Text="{Binding Path=Model.SelectedNoteBook.OriginalDate, StringFormat='f', ConverterCulture={x:Static gl:CultureInfo.CurrentCulture}" FontSize="20"TextTrimming="CharacterEllipsis" />

我很清楚这不是一个全局修复,你会在每个Bindings上都需要它,但这肯定是好的XAML?据我所知,下次绑定更新时,它将使用正确的CultureInfo.CurrentCulture或您提供的任何内容。

This solution will immediately update your Bindings with the correct values但似乎很多代码都是如此罕见和无害。

答案 2 :(得分:10)

只需将文化快捷方式插入顶级标记:

xml:lang="de-DE"

e.g:

<Window x:Class="MyApp"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xml:lang="de-DE"
    Title="MyApp" Height="309" Width="497" Loaded="Window_Loaded">....</Window>

答案 3 :(得分:10)

我只想补充说, loraderon 的答案在大多数情况下都很有用。当我在App.xaml.cs中放入以下代码行时,我的TextBlocks中的日期格式正确。

FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

我说'大多数情况'。例如,这将开箱即用:

<TextBlock Text="{Binding Path=Date, StringFormat={}{0:d MMMM yyyy}}" />
--> "16 mei 2013" (this is in Dutch)

...但是在TextBlock中使用Run时,DateTime的格式为默认文化。

<TextBlock>
  <Run Text="Datum: " />
  <Run Text="{Binding Path=Date, StringFormat={}{0:d MMMM yyyy}, Mode=OneWay}" />
</TextBlock>
--> "Datum: 16 may 2013" (this is in English, notice the
    name of the month "may" vs. "mei")

为此,我需要 Gusdor 的答案,即将ConverterCulture = {x:Static gl:CultureInfo.CurrentCulture}添加到Binding。

<TextBlock>
  <Run Text="Datum: " />
  <Run Text="{Binding Path=Date, StringFormat={}{0:d MMMM yyyy}, ConverterCulture={x:Static gl:CultureInfo.CurrentCulture}, Mode=OneWay}" />
</TextBlock>
--> "Datum: 16 mei 2013" (=Dutch)

我希望这个额外的答案对某人有用。

答案 4 :(得分:9)

如前所述,XAML默认为不变文化(en-US),您可以使用

FrameworkElement.LanguageProperty.OverrideMetadata(
  typeof(FrameworkElement),
  new FrameworkPropertyMetadata(
      XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

将文化设置为当前文化语言的默认文化。但评论是错误的;这使用当前文化,因为您将看不到用户可能进行的任何自定义,它将始终是该语言的默认设置。

要将当前文化与自定义结合使用,您需要将ConverterCultureStringFormat一起设置,如

Text="{Binding Day, StringFormat='d', ConverterCulture={x:Static gl:CultureInfo.CurrentCulture}}"

gl定义为根元素中的全局命名空间

xmlns:gl="clr-namespace:System.Globalization;assembly=mscorlib"

答案 5 :(得分:8)

如果你需要在程序运行时更改语言,你可以只更改根元素的语言属性(我不确定这是否具有即时效果,或者是否必须重新创建子元素,在我的情况下这是有效的至少)

element.Language = System.Windows.Markup.XmlLanguage.GetLanguage(culture.IetfLanguageTag);

答案 6 :(得分:6)

<Run />等元素中切换本地化的完整代码是:

Private Shared Sub SetXamlBindingLanguage()

    '' For correct regional settings in WPF (e.g. system decimal / dot or comma) 
    Dim lang = System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(TextElement), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(DefinitionBase), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(FixedDocument), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(FixedDocumentSequence), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(FlowDocument), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(TableColumn), New FrameworkPropertyMetadata(lang))
    FrameworkElement.LanguageProperty.OverrideMetadata(GetType(FrameworkElement), New FrameworkPropertyMetadata(lang))

End Sub

答案 7 :(得分:0)

如果您想在运行时更改文化信息,可以使用行为(见下文)

  public class CultureBehavior<TControl> : Behavior<TControl>
    where TControl : FrameworkElement
{
    private readonly IEventAggregator _eventAggregator;
    private readonly Action<CultureInfo> _handler;

    public CultureBehavior()
    {
        _handler = (ci) => this.AssociatedObject.Language = XmlLanguage.GetLanguage(ci.IetfLanguageTag);
        _eventAggregator = IoC.Container.Resolve<IEventAggregator>();
    }

    protected override void OnAttached()
    {
        base.OnAttached();

        _eventAggregator
            .GetEvent<LanguageChangedEvent>()
            .Subscribe(_handler);

        _handler.Invoke(CultureInfo.CurrentCulture);
    }

    protected override void OnDetaching()
    {
        _eventAggregator
            .GetEvent<LanguageChangedEvent>()
            .Unsubscribe(_handler);

        base.OnDetaching();
    }
}

答案 8 :(得分:0)

如果您正在处理代码而不是XAML,可以按如下方式设置ConverterCulture:

binding.ConverterCulture = System.Globalization.CultureInfo.CurrentCulture;

感谢@KZeise指出使用默认文化定义和使用用户自定义文化定义之间的细微差别。

答案 9 :(得分:-3)

使用标签(包括文化)而不是文本块