2011-04-29 2 views
30

В моем случае:Использования «реальное» CultureInfo.CurrentCulture в WPF Binding, не CultureInfo из IetfLanguageTag

У меня есть TextBlock Привязка к свойству типа DateTime. Я хочу, чтобы он отображался в качестве региональных настроек пользователя.

<TextBlock Text="{Binding Date, StringFormat={}{0:d}}" /> 

Я устанавливаю язык собственность как WPF XAML Bindings and CurrentCulture Display говорит:

this.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag); 

Но с этой строки кода он просто отображает текст в формате по умолчанию CultureInfo с IetfLanguageTag из CurrentCulture говорит, а не как эффективное значение, выбранное в настройках области системы, указано:

(например, для «de-DE» dd.MM.yyyy используется вместо выбора ред гггг-ММ-дд)

Region settings: not the default but yyy-MM-dd is used

Есть ли способ Binding использует правильный формат без определения ConverterCulture на каждый Binding?

В коде

string.Format("{0:d}",Date); 

использует правильные настройки культуры.

редактировать:

другой путь, который не работает по желанию (например, this.Language = ... делает):

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

и

<Binding Source="{x:Static glob:CultureInfo.CurrentCulture}" 
Path="IetfLanguageTag" 
ConverterCulture="{x:Static glob:CultureInfo.InvariantCulture}" /> 
+1

проверьте следующее: http://stackoverflow.com/questions/2764615/wpf-stringformat-0c-showing-as-dollars –

+2

@Pavlo: ответ на этот вопрос также использует IetfLanguageTag для получения CultureInfo. –

ответ

22

Вы можете создайте подкласс связывания (например, CultureAwareBinding), который автоматически преобразует ConverterCulture в текущую культуру при создании.

Это не идеальное решение, но, вероятно, это единственное, поскольку ретроактивное форсирование Привязка к уважению культуры может нарушить другой код в WPF, который зависит от этого поведения.

Дайте мне знать, если вам нужна дополнительная помощь!

+0

Благодарим вас за ответ. это решение является единственным возможным. –

+0

", поскольку ретроактивное форсирование Привязка к уважению к культуре может разорвать другой код в WPF, который зависит от этого поведения." - Я бы сказал, что в долгосрочной перспективе хуже продолжать поддерживать нарушенное поведение, чем это значит ввести кратковременный перерыв. Или они могут исправить это, но использовать функции привязки сборки .NET, чтобы обнаружить, когда приложение ожидает более старую версию и поддерживает нарушенное поведение для них. Это безумие, что эта ошибка была в WPF уже 12 лет, и у них нет встроенного встроенного встроенного редактора CultureAwareBinding. – Dai

2

Ваша вторая попытка была близка и привела меня к решению, которое действительно работает для меня.

Проблема с настройкой ConverterCulture заключается в том, что она используется только при наличии конвертера. Так просто создать простой StringFormatConverter, который принимает формат в качестве параметра:

public sealed class StringFormatConverter : IValueConverter 
{ 
    private static readonly StringFormatConverter instance = new StringFormatConverter(); 
    public static StringFormatConverter Instance 
    { 
     get 
     { 
      return instance; 
     } 
    } 

    private StringFormatConverter() 
    { 
    } 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return string.Format(culture, (string)parameter, value); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 

Затем вы можете настроить привязки (при условии, вы импортировали пространство имен преобразователя, как «мой»)

<TextBlock Text="{Binding Date, Converter={x:Static my:StringFormatConverter.Instance}, ConverterCulture={x:Static glob:CultureInfo.CurrentCulture}, ConverterParameter={}{0:d}}" /> 
-1

Как насчет изменить lanaguge в коде позади?

this.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name); 
+0

Этот метод игнорирует пользовательские настройки в диалоговом окне «Регион и язык» и просто использует имя для получения языка. –

+0

Это простейшее решение и отлично работает для меня (Windows Phone 7). @Markus k: Извините, не понял, что вы пытаетесь сказать/объяснить? – hfrmobile

+1

@hfmobile Что он имел в виду, так это то, что если вы выберете язык в региональных настройках (например, немецкую Германию), а затем вручную измените какие-либо настройки (с изменением короткой даты на dMyyyy), установка языка, предложенного выше, не будет новый формат. – Goran

15

Это расширение ответа от aKzenT. Они предложили создать подкласс класса Binding и установить ConverterCulture в CurrentCulture. Несмотря на то, что ответ очень прямолинейный, я чувствую, что некоторые люди могут не очень удобно его реализовать, поэтому я использую версию кода ответа aKzenT на примере использования XAML.

using System; 
using System.Globalization; 
using System.Windows.Data; 

namespace MyWpfLibrary 
{ 
    public class CultureAwareBinding : Binding 
    { 
     public CultureAwareBinding() 
     { 
      ConverterCulture = CultureInfo.CurrentCulture; 
     } 
    } 
} 

Пример того, как использовать это в XAML

1) Вы должны импортировать пространство имен в файле XAML:

<Page 
    ... 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:myWpfLib="clr-namespace:MyWpfLibrary;assembly=<assembly_name>" 
    ... 
> 

2) в реальном мире в CultureAwareBinding

<Textblock Text="{myWpfLib:CultureAwareBinding Path=Salary, Source=Contact, StringFormat={}{0:C}}" /> 
+0

Мне нравится ваше подробное объяснение по этому вопросу. Любой ввод исправления ошибок для определенных привязок? Это приводит к чему-то вроде: «Тип« CultureAwareBinding »не включает конструктор с указанным числом аргументов». – Poken1151

+0

Я еще не видел эту ошибку. Мне нужно будет увидеть код, чтобы определить, почему это произойдет. Возможно, вы могли бы опубликовать новый вопрос о переполнении стека и добавить ссылку на него здесь? –

+1

Спасибо, я исправил ошибку. Это было плохое кодирование, очевидно, {Binding ITEM-NAME ....} нехорошо, мне нужно {Binding Path = ITEM-NAME, ...}. Это разрешило мою ошибку (которая все равно будет компилироваться в обоих случаях) – Poken1151

-1

Проблема, заключающаяся в том, что вы избегаете использования «this.Language = XmlLanguage.GetLanguage (Thread.Current Thread.CurrentCulture.Name);» на самом деле не является общим. Я не знаю ни одного пользователя здесь, во Франции, который изменит формат даты на американский или японский, только потому, что, по крайней мере, ни один пользователь не знает, что такое изменение возможно (и не знаю, как это сделать) ... So конечно, «язык =» не идеален, но за многие годы практики WPF и Silverlight я никогда не вижу проблемы такого рода с любым пользователем ... Так что я все еще использую трюк «Langage =», это просто и покрывают 100% реальных потребностей. Конечно, другие решения кажутся лучше, но нет необходимости (и я видел несколько реализаций, которые далеки от совершенства по сравнению с решением «language =»).

+1

@ Оливье: просто говоря: «Другие пользователи даже не знают о таком варианте», «из моих многолетних знаний WPF и Silverlight, которые я знаю лучше всего» или даже утверждают, что кто-то знает, что «реальные потребности людей» высокомерны. Вы ничего не знаете о предпочтениях почти 99% людей этой планеты - так же, как и все остальные разработчики. Примите, что есть необходимость и помощь. Использование YYYY-MM-DD - формат даты, который я пожелал, чтобы весь мир скорее согласился, чем использовать свои региональные. ИМХО «от большого к маленькому» более полезно, особенно когда речь идет о сортировке, чем любой другой формат. – Yoda

1

Я использую этот код с надлежащими результатами для моих нужд. Надеюсь, это может заполнить ваши :-)! Возможно, вы лучше выбрасываете исключение, если не можете «TryParse». Вам решать.

public sealed class CurrentCultureDoubleConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return ((double)value).ToString((string)parameter ?? "0.######", CultureInfo.CurrentCulture); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     double result; 
     if (Double.TryParse(value as string, NumberStyles.Number, CultureInfo.CurrentCulture, out result)) 
     { 
      return result; 
     } 

     throw new FormatException("Unable to convert value:" + value); 
     // return value; 
    } 
} 

Использование:

<Window 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:simulatorUi="clr-namespace:SimulatorUi" 
     xmlns:Converter="clr-namespace:HQ.Wpf.Util.Converter;assembly=WpfUtil" x:Class="SimulatorUi.DlgTest" 
     Title="DlgTest" Height="300" Width="300"> 
    <Window.DataContext> 
     <simulatorUi:DlgTestModel/> 
    </Window.DataContext> 

    <Window.Resources> 
     <Converter:CurrentCultureDoubleConverter x:Key="CurrentCultureDoubleConverter"/> 
    </Window.Resources> 

    <Grid> 
     <TextBox Text="{Binding DoubleVal, Converter={StaticResource CurrentCultureDoubleConverter}}"/> 
    </Grid> 
</Window> 
2

Я придумал хак/обходной путь, который позволяет избежать обновления всех ваших привязок. Добавьте этот код в конструктор вашего главного окна.

XmlLanguage language = XmlLanguage.GetLanguage("My-Language"); 
typeof(XmlLanguage).GetField("_compatibleCulture", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(language, CultureInfo.CurrentCulture); 
this.Language = language; 

Поскольку это с помощью отражения нет никакой гарантии, что он будет работать в будущем, но сейчас это делает (.NET 4.6).

3

Поместите следующую строку кода перед инициализацией пользовательского интерфейса. Это сработало для меня.

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

(и удалить все явные параметры культуры)

Смежные вопросы