i18n (Интернационализация) в WPF и Silverlight. Числовые поля

добавлено: 25 июн 14
понравилось:0
просмотров: 1162
комментов: 0

теги:

Автор: gpu

Введение.
Представим себе что у нас есть число 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.

Комментарии




Необходимо войти на сайт, чтобы оставлять комментарии