在wpf中的StringFormat本地化问题
在WPF 3.5SP1中,我使用了DataBindings中的最后一个特性StringFormat:
<TextBlock Text="{Binding Path=Model.SelectedNoteBook.OriginalDate, StringFormat='f'}" FontSize="20" TextTrimming="CharacterEllipsis" />
我面对的问题是,date总是用英语格式化…虽然我的系统是法语的吗? 我如何强制date跟随系统date?
// 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)));
在WPF中创build一个国际化的向导
定义下面的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" />
我很清楚这不是一个全球性的解决scheme,你会在你的每一个绑定需要它,但肯定这只是一个好的XAML? 据我所知,下一次绑定更新它将使用正确的CultureInfo.CurrentCulture
或任何你提供的。
此解决scheme将立即更新您的绑定与正确的值,但它似乎很多代码的东西如此罕见和无害。
只需将文化快捷方式插入顶级标记即可:
xml:lang="de-DE"
例如:
<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>
如果你需要在程序运行的时候改变语言,你可以改变你的根元素的语言属性(我不确定这是否有即时的效果,或者是否需要重新创build子元素,在我的情况下,这至less是有效的)
element.Language = System.Windows.Markup.XmlLanguage.GetLanguage(culture.IetfLanguageTag);
我只是想补充一点,在大多数情况下, loraderon的答案很好。 当我把下面这行代码放在我的App.xaml.cs中时,我的TextBlocks中的date被格式化为正确的文化。
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}到绑定。
<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)
我希望这个额外的答案将被用于某人。
如前所述,XAML默认为不变文化(en-US),您可以使用
FrameworkElement.LanguageProperty.OverrideMetadata( typeof(FrameworkElement), new FrameworkPropertyMetadata( XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
把文化设定为当前文化语言的默认文化。 但是评论是错误的; 这不会使用当前的文化,因为您不会看到用户可能做出的任何自定义,它始终是该语言的默认设置。
要通过自定义实际使用当前文化,您需要将ConverterCulture
与StringFormat
一起设置,如
Text="{Binding Day, StringFormat='d', ConverterCulture={x:Static gl:CultureInfo.CurrentCulture}}"
将gl
定义为根元素中的全局名称空间
xmlns:gl="clr-namespace:System.Globalization;assembly=mscorlib"
在<Run />
元素中切换本地化的完整代码是这样的:
Private Shared Sub SetXamlBindingLanguage() '' For correct regional settings in WPF (eg 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
如果你想在运行时改变文化信息,你可以使用一个行为(见下文)
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(); } }
使用标签(包括Cultture)而不是texblock