Подтвердить что ты не робот

Проблемы с локализацией строки StringFormat в wpf

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

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

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

4b9b3361

Ответ 2

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

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

Ответ 3

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

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>

Ответ 4

Я просто хотел добавить, что ответ 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)

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

Для этого мне понадобился ответ Гусдор, а именно добавление в привязку 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)

Я надеюсь, что этот дополнительный ответ будет полезен кому-то.

Ответ 5

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

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

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

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

Ответ 10

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