StringFormat Проблемы с локализацией в wpf - PullRequest
107 голосов
/ 06 февраля 2009

В WPF 3.5SP1 я использую последнюю функцию StringFormat в DataBindings:

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

Проблема, с которой я сталкиваюсь, заключается в том, что дата всегда форматируется на английском языке ... хотя моя система на французском? Как я могу заставить дату следовать системной дате?

Ответы [ 10 ]

199 голосов
/ 06 февраля 2009
// 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

81 голосов
/ 21 июня 2011

Определите следующее пространство имен 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" />

Я хорошо знаю, что это не глобальное исправление, и вам потребуется его для каждой привязки, но, конечно, это просто хороший XAML? Насколько я знаю, при следующем обновлении привязки будет использоваться правильный CultureInfo.CurrentCulture или что-то еще, что вы предоставили.

Это решение немедленно обновит ваши привязки с правильными значениями , но кажется, что для большого количества редких и безобидных кодов много.

10 голосов
/ 16 мая 2013

Я просто хотел добавить, что ответ loraderon прекрасно работает в большинстве случаев. Когда я добавляю следующую строку кода в мой файл App.xaml.cs, даты в моих текстовых блоках форматируются в правильной культуре.

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)

... но при использовании Run в TextBlock 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)

Надеюсь, этот дополнительный ответ кому-нибудь пригодится.

10 голосов
/ 02 ноября 2012

Просто вставьте ярлык культуры в тег верхнего уровня:

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>
9 голосов
/ 06 февраля 2015

Как уже говорилось, 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"
8 голосов
/ 02 марта 2011

Если вам нужно изменить язык во время работы программы, вы можете просто изменить свойство Language вашего корневого элемента (я не уверен, что это дает мгновенный эффект, или если подэлемент необходимо воссоздать, в моем случае это работает как минимум)

element.Language = System.Windows.Markup.XmlLanguage.GetLanguage(culture.IetfLanguageTag);
6 голосов
/ 28 июля 2014

Полный код для переключения локализации также в таких элементах, как <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
0 голосов
/ 29 января 2018

Если вы работаете с кодом, а не с XAML, вы можете установить ConverterCulture следующим образом:

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

Спасибо @KZeise за то, что он указал на тонкую разницу между использованием определения культуры по умолчанию и использованием пользовательского определения культуры.

0 голосов
/ 07 марта 2014

Если вы хотите изменить информацию о культуре во время выполнения, вы можете использовать поведение (см. Ниже)

  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();
    }
}
0 голосов
/ 25 февраля 2010

Использовать ярлык (включая культуру), а не тексблок

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...