Автор: gpu
Введение.
Представим себе что у нас есть число 1234,56 которое надо отобразить в нашем приложении в поле ввода или в гриде.
На компьютере с региональными настройками Америки, число должно отобразиться так:
1,234.56
На компьютере с региональными настройками Германии, число должно отобразиться так:
1.234,56
Проблема заключается в том что внутренние механизмы WPF и Silverlight не совсем правильно используют региональные настройки.
В интернете можно найти достаточно много решений, например:
Silverlight and Application Globalization – The Converter Approach
К сожалению данный вариант не позволяет решить проблему полностью.
Поскольку мне не удалось "выгуглить" метод, который бы позволял решить данную проблему в комплексе, предлагаю свой вариант решения для данной проблемы.
Решение для ВПФ.
1. Переопределениe мета информации у FrameworkElement.
Ето можно сделать в классе Application
2. Переопределение Binding
Используя MarkupExtensions создаем свой CustomBinding унаследованный от Binding и принудительно устанавливаем ConverterCulture в CultureInfo.CurrentCulture
В xaml-e используем CustomBinding вместо стандартного Binding там где ето оправдано, т.е. числовые поля.
3. Конвертер
Код конвертера достаточно тривиален, например:
И даже если мы поменяем региональные настройки.
Например:
десятичный разделитель заменить на #
тысячный на ?
То увидим что число 1234,56 будет отображаться как
1#234?56
И наоборот, если пользователь введет
2#987?01
то мы получим корректное число
2987,01
Решение для Silverlight
Решение аналогично с ВПФ, единственное метод FrameworkElement.LanguageProperty.OverrideMetadata нам не доступен
и CustomBinding наследуем от MarkupExtensions.
Представим себе что у нас есть число 1234,56 которое надо отобразить в нашем приложении в поле ввода или в гриде.
На компьютере с региональными настройками Америки, число должно отобразиться так:
1,234.56
На компьютере с региональными настройками Германии, число должно отобразиться так:
1.234,56
Проблема заключается в том что внутренние механизмы WPF и Silverlight не совсем правильно используют региональные настройки.
В интернете можно найти достаточно много решений, например:
Silverlight and Application Globalization – The Converter Approach
К сожалению данный вариант не позволяет решить проблему полностью.
Поскольку мне не удалось "выгуглить" метод, который бы позволял решить данную проблему в комплексе, предлагаю свой вариант решения для данной проблемы.
Решение для ВПФ.
1. Переопределениe мета информации у FrameworkElement.
FrameworkElement.LanguageProperty.OverrideMetadata(GetType(FrameworkElement), New FrameworkPropertyMetadata(Markup.XmlLanguage.GetLanguage(Globalization.CultureInfo.CurrentCulture.IetfLanguageTag)))
Ето можно сделать в классе Application
Protected Overrides Sub OnStartup(e As Windows.StartupEventArgs) FrameworkElement.LanguageProperty.OverrideMetadata(GetType(FrameworkElement), New FrameworkPropertyMetadata(Markup.XmlLanguage.GetLanguage(Globalization.CultureInfo.CurrentCulture.IetfLanguageTag))) MyBase.OnStartup(e) End Sub
2. Переопределение Binding
Используя MarkupExtensions создаем свой CustomBinding унаследованный от Binding и принудительно устанавливаем ConverterCulture в CultureInfo.CurrentCulture
В xaml-e используем CustomBinding вместо стандартного Binding там где ето оправдано, т.е. числовые поля.
3. Конвертер
Код конвертера достаточно тривиален, например:
Public Class DoubleConverter Implements IValueConverter Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert Dim dv As Double = CDbl(value) Dim frmtString As String = "N2" If parameter IsNot Nothing Then If TryCast(parameter, String) IsNot Nothing Then frmtString = CStr(parameter) End If End If Return dv.ToString(frmtString, culture) End Function Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack Dim ret As Double Dim stringValue As String = CStr(value) Dim style As NumberStyles = NumberStyles.Number Double.TryParse(stringValue, style, culture, ret) Return ret End Function End Class
И даже если мы поменяем региональные настройки.
Например:
десятичный разделитель заменить на #
тысячный на ?
То увидим что число 1234,56 будет отображаться как
1#234?56
И наоборот, если пользователь введет
2#987?01
то мы получим корректное число
2987,01
Решение для Silverlight
Решение аналогично с ВПФ, единственное метод FrameworkElement.LanguageProperty.OverrideMetadata нам не доступен
и CustomBinding наследуем от MarkupExtensions.
Комментарии