This article is currently in the process of being translated into Bulgarian (~98% done).
Culture / UICulture на приложението
Ако сте работили малко с числа или дати във вашето WPF приложение, напр. поради една от статиите, намерени в този урок, може да сте забелязали нещо страхотно: числата и датите се показват автоматично във формат, който съответства на формата, използван на вашия компютър. Ако живеете в англоговоряща страна, това вероятно не е кой знае какво, но ако живеете в една от МНОГОТО страни, където датите и/или числата се показват по различен начин, това е наистина страхотно.
И ако си мислите „със сигурност не може да има толкова много разлики при форматиране на прости неща като числа и дати?“, предлагам ви да погледнете това примерно приложение, където съм форматирал същото число и същата дата в съответствие с това как го предпочитат в САЩ, Германия и Швеция:
Както можете да видите, има много фини разлики в това как се показват числата и датите. Добрата новина е, че .NET framework може да ви помогне много - всъщност то вече го прави: По подразбиране датите и числата са форматирани в съответствие със системните настройки на компютъра, на който се изпълнява вашето приложение. Лошата новина е, че това поведение не винаги е такова, каквото го искате. Но не се притеснявайте - можете лесно да промените това. Всичко е свързано с използването на класа CultureInfo, за който можете да прочетете много повече на C# статия с уроци за CultureInfo. Засега нека обсъдим как да приложим тези техники към вашето WPF приложение.
Ad-hoc форматиране
Ако трябва да приложите форматиране само за определена част от информацията, напр. съдържанието на една контрола Label, можете лесно да направите това, в движение, като използвате комбинация от метода ToString() и класа CultureInfo. Например в примера по-горе приложих различно, в зависимост от страната форматиране по следния начин:
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);
Това може да е достатъчно за някои случаи, когато просто се нуждаете от специално форматиране на няколко места, но като цяло трябва да решите дали приложението ви трябва да използва системни настройки (по подразбиране) или трябва да замените това поведение с конкретна настройка за страната за цялото приложение.
CurrentCulture и CurrentUICulture
Прилагането на други регионални настройки (или "култури", за по лесно асоцииране с използвана терминология) към вашето WPF приложение е доста лесно. Потенциално ще имате работа с два атрибута, към свойството CurrentThread на класа Thread: CurrentCulture и CurrentUICulture. Но каква е разликата?
Атрибута CurrentCulture е това, което контролира как се форматират числата, датите и т.н. Стойността по подразбиране идва от операционната система на компютъра, изпълняващ приложението, и може да се променя независимо от езика, използван от тяхната операционна система. Например, много обичайно е човек, живеещ в Германия, да инсталира Windows с английски като език на интерфейса, като същевременно предпочита немска нотация за числа и дати. За ситуация като тази CurrentCulture по подразбиране ще бъде немски.
Свойството CurrentUICulture указва езика, който трябва да използва интерфейсът. Това е от значение само ако вашето приложение поддържа няколко езика, напр. чрез използване на файлове с езикови ресурси. Още веднъж, това ви позволява да използвате една настройка за езика (напр. английски), докато използвате друга (напр. немски), когато работите с въвеждане/извеждане на числа, дати и т.н.
Промяна в регионалните настройки на приложението
Имайки предвид всичко по-горе, сега трябва да решите дали да промените CurrentCulture и/или CurrentUICulture. Това може да се направи почти винаги, когато пожелаете, но е най-разумно да го направите, когато стартирате приложението си - в противен случай някои резултати може вече да са показват с други настройки по подразбиране, преди превключването. Ето пример, в който променяме настройките, както и UICulture, в събитието Application_Startup(), което може да се използва във файла App.xaml.cs на вашето WPF приложение:
private void Application_Startup(object sender, StartupEventArgs e)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
}
Тъй като използваме класа Thread, както и CultureInfo, не забравяйте да добавите необходимите импорти "using" към вашия файл, ако те вече не са налични:
using System.Threading;
using System.Globalization;
Сега вече числата и датите ще бъдат форматирани според предпочитанията им на немски (de-DE). Както споменахме, можете да пропуснете реда, определящ културата за UICulture (последния ред), ако приложението ви не поддържа няколко езика.
Промяната на регионалните настройки по време на Application_Startup или най-късно в конструктора на вашия главен прозорец има най-голям смисъл, тъй като стойностите, които вече са генерирани, не се актуализират автоматично, когато промените CurrentCulture . Това обаче не означава, че не можете да го направите, както е илюстрирано от този следващ пример, който също служи като добра демонстрация на това как изходът се влияе от стойностите на CurrentCulture:
<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();
}
}
}
Интересната част се намира в метода CultureInfoSwitchButton_Click, където задаваме CurrentCulture въз основа на това кой от бутоните е натиснат и след това актуализираме двата етикета, съдържащи число и дата:
Culture и Threads: DefaultThreadCurrentCulture свойството
Ако вашето приложение използва повече от една нишка, трябва да обмислите използването на свойството DefaultThreadCurrentCulture. Може да се намери в класа CultureInfo (въведен в .NET framework версия 4.5). То гарантира, че не само текущата нишка, но и бъдещите нишки ще използват същите настройки. Можете да го използвате по следния начин, напр. в Application_Startup:
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de-DE");
И така, трябва ли да зададете стойност и заCurrentCulture И за DefaultThreadCurrentCulture? Всъщност не - ако все още не сте променили CurrentCulture, настройката на DefaultThreadCurrentCulture също ще бъде приложена към CurrentCulture. С други думи, има смисъл да използвате DefaultThreadCurrentCulture вместо CurrentCulture, ако планирате да използвате множество нишки във вашето приложение - така ще се погрижите за всички възможни сценарии.
Обобщение
Нагласянето на регионалните настойки на вашето WPF приложение е много важно, но за ваше улеснение, WPF прави само голяма част от нещата. Ако трябва да промените поведението по подразбиране, това също е доста лесно, като използвате CurrentCulture и CurrentUICulture, както бе илюстрирано в многобройните примери в тази статия.