This article has been localized into Portuguese by the community.
Culture / UICulture de Aplicação
Se você já trabalhou um pouco com números e datas em sua aplicação WPF, por exemplo, por causa de algum dos artigos encontrados neste tutorial, pode ter notado algo interessante: números e datas são automaticamente mostrados em um formato que se adéqua àquele utilizado em seu computador. Se você mora em um país de língua inglesa, isso provavelmente não parece lá grande coisa, mas se morar em um dos MUITOS países em que datas e/ou números são mostrados de forma diferente, isto é realmente legal.
E se você está pensando "sério que há tantas diferenças assim quando se formata coisas simples tais como números e datas?", eu sugiro que você dê uma olhada neste exemplo de aplicação em que formatei o mesmo número e a mesma data de acordo com as preferências locais dos Estados Unidos, Alemanha e Suécia.
Então como você pode ver, há muitas diferenças sutis em como números e datas são exibidos. A boa notícia é que o framework .NET pode te ajudar muito - na verdade, ele já o faz: por padrão, datas e números são formatados de acordo com as definições do sistema do computador em que sua aplicação é executada. A má notícia é que esse comportamento nem sempre é o que você quer. Mas não se preocupe - você pode facilmente alterar isto. Tudo se baseia na utilização da classe CultureInfo, sobre a qual você pode ler muito mais em C# Tutorial article on CultureInfo. Por ora, vamos examinar como aplicar essas técnicas em sua aplicação WPF.
Formatação ad-hoc
Se você precisa aplicar uma formatação somente em uma parte específica de alguma informação, por exemplo, no conteúdo de um simples controle Label, pode facilmente obter isto, no mesmo ponto, utilizando uma combinação do método ToString() com a classe CultureInfo. Como consta, no exemplo acima, eu apliquei diferentes formatações baseadas em cultura, tais como estas:
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);
Isso pode ser suficiente para alguns casos, onde você precisa de uma formatação especial em alguns locais, mas em geral, tem que decidir se sua aplicação deverá utilizar as preferências do sistema (o padrão) ou se deverá substituir este comportamento pelo de uma configuração específica de cultura para toda a aplicação.
CurrentCulture & CurrentUICulture
Aplicar uma outra preferência de cultura em sua aplicação WPF é bem fácil. Potencialmente você estará lidando com dois atributos encontrados na propriedade CurrentThread da classe Thread: CurrentCulture e CurrentUICulture. Mas qual a diferença?
A propriedade CurrentCulture é aquela que controla como números, datas, etc. são formatados. O valor padrão advém do sistema operacional do computador que está executando a aplicação e pode ser alterado independentemente da língua utilizada por este sistema. Isto é muito comum, por exemplo, para uma pessoa que vive na Alemanha e instala o Windows com inglês como sua interface de língua, enquanto ainda prefere a notação germânica para números e datas. Para uma situação como esta, a propriedade CurrentCulture padrão estaria configurada para Alemão.
A propriedade CurrentUICulture especifica qual língua a interface deverá utilizar. Isto é relevante somente se sua aplicação dá suporte a múltiplas linguagens, por exemplo, através do uso de arquivos de recursos de línguas. Mais uma vez, isto permite que você utilize uma cultura para a língua (ex. inglês) enquanto utiliza outra (ex. Alemão) para lidar com entrada/saída de números, datas, etc.
Alterando a Cultura da aplicação
Tendo isto em mente, agora você deverá decidir se altera a CurrentCulture e/ou a CurrentUICulture. Isto pode ser feito praticamente a qualquer momento em que você quiser, mas faz mais sentido se for no início da aplicação - caso contrário, alguma saída poderá já ter sido gerada com a cultura padrão, antes da mudança. Aqui há um exemplo onde alteramos a Culture, bem como a UICulture, no evento Application_Startup() que pode ser utilizado no arquivo App.xaml.cs de sua aplicação WPF.
private void Application_Startup(object sender, StartupEventArgs e)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
}
Uma vez que estamos utilizando a classe Thread, bem como a CultureInfo, não se esqueça de adicionar os namespaces necessários ao seu arquivo, se eles ainda não estiverem presentes.
using System.Threading;
using System.Globalization;
Feito isto, números e datas agora serão formatados de acordo com o que foi definido, isto é, em Alemão (de-DE). Como mencionado antes, você pode ignorar a linha que define a cultura para a UICulture (a última linha) caso sua aplicação não dê suporte a múltiplas linguagens.
Alterar a cultura durante o evento Application_Startup, ou, em última instância, no construtor de sua janela principal, faz mais sentido, pois os valores que já foram gerados anteriormente não serão atualizados automaticamente quando se alterar a propriedade CurrentCulture. No entanto, não significa que você não possa fazer isto, como ilustrado por este próximo exemplo, que também serve como uma boa demonstração de como a saída é afetada pela propriedade 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();
}
}
}
A parte interessante está no evento CultureInfoSwitchButton_Click, onde definimos a CurrentCulture baseados em qual dos botões se clicou, e então atualizamos os dois labels contendo um número e uma data:
Culture & Threads: A propriedade DefaultThreadCurrentCulture
Se sua aplicação utiliza mais de um processo, você deve considerar a hipótese de utilizar a propriedade DefaultThreadCurrentCulture. Ela pode ser encontrada na classe CultureInfo (introduzida no framework .NET versão 4.5) e assegurará que, não apenas o processo atual, mas como também todos os processos futuros utilizem a mesma cultura. Você pode utiliza-la, por exemplo, no evento Application_Startup:
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de-DE");
Então você terá que definir ambas propriedades CurrentCulture E DefaultThreadCurrentCulture? Na verdade, não - caso você ainda não tenha alterado a propriedade CurrentCulture, definir a propriedade DefaultThreadCurrentCulture também se aplicará a CurrentCulture. Em outras palavras, faz sentido utilizar DefaultThreadCurrentCulture ao invés de CurrentCulture se você planeja utilizar múltiplos processos em sua aplicação - isto cobrirá todos os cenários.
Sumário
Lidar com cultura em sua aplicação WPF é muito importante, e felizmente para você, o WPF cuidará de grande parte do trabalho completamente fora da vista. Se você precisar alterar o comportamento padrão, é bem simples, basta utilizar as propriedades CurrentCulture e CurrentUICulture, como ilustrado nos vários exemplos deste artigo.