wpf 中的 StringFormat 本地化问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/520115/
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-08 20:01:51  来源:igfitidea点击:

StringFormat Localization issues in wpf

wpfdatetimelocalization

提问by loraderon

In WPF 3.5SP1 i use the last feature StringFormat in DataBindings:

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

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

The problem I face is that the date is always formatted in English...although my system is in French ? How can i force the date to follow system date?

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

回答by loraderon

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

From Creating an Internationalized Wizard in WPF

在 WPF 中创建国际化向导

回答by Gusdor

Define the following xml namespace:

定义以下 xml 命名空间:

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

Now behold this fantastic fix:

现在看看这个奇妙的修复:

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

I'm well aware this isn't a global fix and you will require it on each of your Bindings but surely that is just good XAML? As far as I'm aware, the next time the binding updates it will use the correct CultureInfo.CurrentCultureor whatever you have supplied.

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

This solution will immediately update your Bindings with the correct valuesbut it seems like a lot of code for something so rare and innocuous.

此解决方案将立即使用正确的值更新您的绑定,但对于如此罕见且无害的东西,它似乎有很多代码。

回答by Dani?l Teunkens

I just wanted to add that loraderon's answer works great in most cases. When I put the following line of code in my App.xaml.cs, the dates in my TextBlocks are formatted in the correct culture.

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

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

I say 'most cases'.For example, this will work out of the box:

我说的是“大多数情况”。例如,这将是开箱即用的:

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

...but when using Run's in a TextBlock, the DateTime is formatted in the default culture.

...但是在 TextBlock 中使用 Run's 时,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")

For this to work, I needed Gusdor's answer, namely adding ConverterCulture={x:Static gl:CultureInfo.CurrentCulture} to the Binding.

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

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

I hope this additional answer will be of use to someone.

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

回答by Gerrit Horeis

Just insert the culture shortcut to the top-level tag:

只需将区域性快捷方式插入顶级标签:

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>

回答by KZeise

As already stated, XAML defaults to the invariant culture (en-US), and you can use

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

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

to set the culture to the default culture for the language of the current culture. But the comment is wrong; this does notuse the current culture, as you will not see any customizations the user might have made, it will always be the default for the language.

将文化设置为当前文化语言的默认文化。但是评论是错误的;这并没有使用目前的文化,因为你不会看到用户可能所做的任何定制,它永远是对语言的默认。

To actually use the current culture with customizations, you will need to set the ConverterCulturetogether with the StringFormat, as in

要在自定义中实际使用当前文化,您需要将 与ConverterCulture一起设置StringFormat,如

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

with the gldefined as a global namespace in your root element

gl您的根元素定义为一个全局命名空间

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

回答by Peter

If you need to change the language while the program is running you can just change the Language property on your root element (im unsure if this has an instant effect or if the sub element have to be recreated, in my case this works at least)

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

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

回答by habakuk

The full code to switch the localization also in elements like <Run />is this:

在元素中切换本地化的完整代码<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

回答by Metalogic

If you are working on code rather than XAML, you can set the ConverterCulture as follows:

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

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

Kudos to @KZeise for pointing out the subtle difference between using the default culture definition and using the user's customized culture definition.

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

回答by user3173620

If you want to change culture info at runtime, you could use a behavior (see below)

如果你想在运行时改变文化信息,你可以使用一个行为(见下文)

  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();
    }
}

回答by david

Use Label (including Cultture) and not texblock

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