Závislost bindingu na nastaveném formátování (kultuře)


Úvod

Při použití klasického bindingu, který zajišťuje zobrazení hodnoty vlastnosti typu double (nebo například decimal) v TextBlocku (nebo TextBoxu atd.), dochází k zobrazení desetinné tečky. Takže například, místo toho, aby se přibindované číslo zobrazilo jako “5,285” zobrazí se jako “5.285”. To je například v České republice špatně a navíc, pokud by uživatel toto číslo měl zadávat (nebo editovat), bylo by pro něj nepohodlné nepoužívat klasické formátování, které má nastavené a na které je zvyklý. K tomuto problému dochází i přes to, že v operačním systému je nastavena například česká kultura a české formátování čísel.

Na stejný problém je možné narazit i v případě dat, které se zobrazí ve formátu “4/26/2011 8:28:31 PM” místo u nás obvyklého “26.4.2011 20:28:31”.

Řešení problému

Tento problém se dá vyřešit několika způsoby:

  • použití konvertoru – například použít metodu ToString(), která nastavenou kulturu zohledňuje
  • použití StringFormat u bindingu – vhodné například pro formátování data
  • použití vlastnosti Language u konkrétních FrameworkElemetů
  • nastavení vlastnosti Language všem FrameworkElementům v aplikaci

První dvě řešení jsou relativně přímočarými a jednoduchými řešeními, ale mají určité nevýhody – je potřeba opakovaně používat konvertor, což může být pro programátora nepohodlné a navíc to může mít i vliv na výkon aplikace. Stejně tak je potřeba opětovně používat StringFormat všude tam, kde chceme formátování použít, navíc to není vhodné pro všechny případy (ale třeba jen pro data).

Dobrým řešením je použít vlastnost třídy FrameworkElement Language, která je právě k tomuto určena – slouží k nastavení jazykové specifikace používané elementem. Vlastnost přebírá objekt typu XmlLanguage, který je možné vytvořit snadno použitím statické metody XmlLanguage.GetLanguage(), která v parametru přebírá řetězec reprezentující jazyk (ve formátu RFC 3066 – například “cs-CZ”, “en-US” atd.). Takto je možné nastavit správné formátování podle vybrané kultury jednomu konkrétnímu elementu.

Ještě lepším řešením je nastavení vlastnosti Language FrameworkElementům globálně v celé aplikaci. To je možné díky tomu, že Language je DependencyProperty a tak můžeme použít následující příkaz (pro nastavení českého formátování):

FrameworkElement.LanguageProperty.OverrideMetadata
    (
        typeof(FrameworkElement), 
        new FrameworkPropertyMetadata(XmlLanguage.GetLanguage("cs-CZ"))
    );

Nebo je možné (což je obecnější a pravděpodobně lepší) nastavit aktuálně používanou kulturu (ať už nastavenou ve Windows nebo v aplikaci, když je použito více jazyků atd.):

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

Tato část kódu by měla být volána po startu aplikace – například v handleru události Application.Startup, ale samozřejmě záleží na každém, kde a kdy chce jazyk nastavit.

Důležité je pamatovat si, že tento příkaz je možné volat pouze jednou, každé další volání skončí výjimkou.

Závěr

Tento problém je způsoben tím, že vlastnost FrameworkElement.Language je vždy defaultně nastavena na “en-US” – což z mého pohledu vypadá dost nelogicky. Proč by měly elementy ve WPF defaultně používat americké formátování a zvyky? Je to úmyslné chování nebo je to chyba?

Pokud má někdo nějaké vysvětlení, proč se nepoužívá jazyk nastavený ve Windows, ať napíše do komentářů. V případě, že se mně podaří zjisti důvod, proč tomu tak je, určitě se tady také objeví.

, , ,

Komentáře jsou uzavřeny.