This article is currently in the process of being translated into Slovak (~59% done).
Application Culture / UICulture
Ak ste už trochu pracovali s číslami alebo dátumami vo vašej WPF aplikácii, napr. preto lebo ste o tom našli článok v tomto tutoriály, tak si možno všimnete niečo super: Čísla a dátumy sa automaticky zobrazujú vo formáte, ktorý zodpovedá systémovému nastaveniu vášho počítača. Ak žijete v anglicky hovoriacej krajine, tak toto pravdepodobne nepovažujete za veľký problém. Ale ak žijete v jednej z MNOHÝCH krajín, v ktorých sa dátumy a/alebo čísla zobrazujú odlišne, tak to oceníte.
A ak si myslíte "určite tam nie je veľa rozdielov pri formátovaní jednoduchých vecí ako ako číselné a dátumové dátové typy." , Navrhujem aby ste sa pozreli na tento príklad, kde som sformátoval rovnaké číslo a dátum podľa toho ako uprednostňujú ich písanie v USA, Nemecku a Švédsku.
Ako môžete vidieť, v zobrazovaní čísel a dátumov je viac rozdielov. Skvelé je, že .NET Framework vám dokáže veľa pomôcť. Dátumy a čísla sú predvolene formátované v súlade so systémovými nastaveniami počítača, na ktorom je spustená vaša aplikácia. Zlou správou je, že toto správanie nemusí byť vždy také, aké chcete. Nemusíte sa báť - toto správanie sa dá ľahko zmeniť. Všetko súvisí s použitím triedy CultureInfo , o ktorej si môžete prečítať oveľa viac na Výučbový článok ohľadom CultureInfo v jazyku C# . Zatiaľ si len povieme, ako túto triedu použiť pre svoju WPF aplikáciu .
Formátovanie Ad-hoc
Ak potrebujete aplikovať formátovanie iba na špecifické miesto, napr. na obsah jednej kontroly Labelov, môžete to urobiť jednoducho, použitím kombinácie ToString() metódy a CultureInfo triedy. Napríklad, v ukážke vyššie, som aplikoval iné formátovanie podľa kultúry, ako toto:
double largeNumber = 123456789.42;
CultureInfo usCulture = new CultureInfo("en-US");
CultureInfo deCulture = new CultureInfo("de-DE");
CultureInfo seCulture = new CultureInfo("sv-SE");
lblNumberUs.Content = largeNumber.ToString("N2", usCulture);
lblNumberDe.Content = largeNumber.ToString("N2", deCulture);
lblNumberSe.Content = largeNumber.ToString("N2", seCulture);
Toto môže postačovať pre niektoré prípady, kde potrebujete špeciálne formátovanie iba v niektorých prípadoch, ale vo všeobecnosti by ste sa mali rozhodnúť, či bude vaša aplikácia používať systémové nastavenia (pôvodne), alebo či prepíšete toto správanie špecifickým kultúrnym nastavením pre celú aplikáciu.
CurrentCulture & CurrentUICulture
Pridávanie ďalšej kultúry do vašej WPF aplikácie je celkom ľahké. Potenciálne sa budete zaoberať dvomi atribútmi, nájdených na CurrentThread vlastnosti Thread triedy: CurrentCulture a CurrentUICulture. Ale aký je rozdiel?
Vlastnosť CurrentCulture je tá, ktorá kontroluje, ako sú čísla, dátumy, atď. formátované. Pôvodná hodnota pochádza z operačného systému počítača, na ktorom aplikácia beží, a môže byť zmenená nezávisle od jazyka používanom v danom operačnom systéme. Je napríklad veľmi časté pre osobu žijúcu v Nemecku inštalovať Windows v angličtine, ako jazyk ich rozhrania, zatiaľ čo na čísla a dátumy preferujú nemeckú notáciu. Pre situáciu, ako táto, je vlastnosť CurrentCulture nastavená pôvodne na nemčinu.
Vlastnosť CurrentUICulture špecifikuje jazyk, ktorý má rozhranie použiť. Toto je relevantné iba, ak vaša aplikácia podporuje viac jazykov, napríklad použitím súborov s jazykmi. Znova, toto vám dovoľuje použiť jednu kultúru pre jazyk (napríklad angličtinu), počas používania iného (napríklad nemčiny) pri spracovávaní vstupu/výstupu čísel, dátumov, atď.
Zmena kultúry aplikácie
Spolu s tým sa musíte rozhodnúť, či zmeníte CurrentCulture a/alebo CurrentUICulture. Môže to byť urobené kedykoľvek, ale najväčší zmysel to dáva pri štarte aplikácie, inak môže byť časť výstupu už vygenerovaná v pôvodnej kultúre, pred zmenou. Tu je príklad, kde meníme kultúru, spolu s UICulture, v Application_Startup() udalosti, ktorá môže byť použitá v App.xaml.cs súbore vašej WPF aplikácie:
private void Application_Startup(object sender, StartupEventArgs e)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
}
Keďže používame triedu Thread a aj CultureInfo, nezabudnite pridať potrebné menné priestory do vášho súboru, ak nie sú prítomné:
using System.Threading;
using System.Globalization;
With this in place, numbers and dates will now be formatted according to how they prefer it in German (de-DE). As mentioned, you can leave out the line defining the culture for the UICulture (the last line) if your application doesn't support multiple languages.
Changing the culture during the Application_Startup event, or at the latest in the constructor of your main window, makes most sense, because values that are already generated aren't updated automatically when you change the CurrentCulture property. That doesn't mean that you can't do it though, as illustrated by this next example, which also serves as a fine demonstration of how the output is affected by the CurrentCulture property:
<Window x:Class="WpfTutorialSamples.WPF_Application.ApplicationCultureSwitchSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTutorialSamples.WPF_Application"
mc:Ignorable="d"
Title="ApplicationCultureSwitchSample" Height="200" Width="320">
<StackPanel Margin="20">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label>Number:</Label>
<Label Name="lblNumber" Grid.Column="1" />
<Label Grid.Row="1">Date:</Label>
<Label Name="lblDate" Grid.Row="1" Grid.Column="1" />
</Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,20">
<Button Tag="en-US" Click="CultureInfoSwitchButton_Click" HorizontalContentAlignment="Stretch">English (US)</Button>
<Button Tag="de-DE" Click="CultureInfoSwitchButton_Click" HorizontalContentAlignment="Stretch" Margin="10,0">German (DE)</Button>
<Button Tag="sv-SE" Click="CultureInfoSwitchButton_Click" HorizontalContentAlignment="Stretch">Swedish (SE)</Button>
</StackPanel>
</StackPanel>
</Window>
using System;
using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
namespace WpfTutorialSamples.WPF_Application
{
public partial class ApplicationCultureSwitchSample : Window
{
public ApplicationCultureSwitchSample()
{
InitializeComponent();
}
private void CultureInfoSwitchButton_Click(object sender, RoutedEventArgs e)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo((sender as Button).Tag.ToString());
lblNumber.Content = (123456789.42d).ToString("N2");
lblDate.Content = DateTime.Now.ToString();
}
}
}
The interesting part is found in the CultureInfoSwitchButton_Click event, where we set CurrentCulture based on which of the buttons were clicked, and then update the two labels containing a number and a date:
Culture & Threads: The DefaultThreadCurrentCulture property
If your application uses more than one thread, you should consider using the DefaultThreadCurrentCulture property. It can be found on the CultureInfo class (introduced in .NET framework version 4.5) and will ensure that not only the current thread, but also future threads will use the same culture. You can use it like this, e.g. in the Application_Startup event:
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de-DE");
So, will you have to set both the CurrentCulture AND the DefaultThreadCurrentCulture properties? Actually, no - if you have not already changed the CurrentCulture property, setting the DefaultThreadCurrentCulture property will also be applied to the CurrentCulture property. In other words, it makes sense to use the DefaultThreadCurrentCulture instead of CurrentCulture if you plan on using multiple threads in your application - it will take care of all scenarios.
Summary
Dealing with the culture of your WPF application is very important, but fortunately for you, WPF will do a lot of it for you completely out-of-the-box. If you need to change the default behavior, it's quite easy as well, using the CurrentCulture and CurrentUICulture properties, as illustrated in the numerous examples of this article.