TOC

This article is currently in the process of being translated into Indonesian (~32% done).

Aplikasi WPF:

Application Culture / UICulture

Jika kamu pernah mengerjakan nomer dan tanggal dalam aplikasi WPF, seperti salah satu artikel yang ditemukan dalam tutorial ini, kamu mungkin mendapatkan sesuatu yang menyenangkan: Nomer dan tanggal secara otomatis ditampilkan dalam format yang sesuai dengan format yang ada dalam komputer kamu. Jika kamu tinggal di negara yang berbahasa Inggris, ini sepertinya merupakan sesuatu yang biasa saja, tapi jika kamu tinggal di negara-negara dimana tanggal dan nomer ditampilkan berbeda, ini sungguh menyenangkan.

Dan jika menurut kamu "Pasti tidak banyak perbedaan ketika memformat hal sederhana seperti angka dan tanggal?", aku sarankan kamu lihat contoh aplikasi berikut, dimana saya memformat angka dan tanggal yang sama untuk negara Amerika Serikat, Jerman dan Swedia:

Jadi seperti yang bisa kamu lihat sendiri, ada banyak perbedaan-perbedaan kecil dalam bagaimana nomer dan tanggal ditampilkan. Untungnya, framework .Net dapat membantu sekali dalam hal ini - bahkan sebenarnya, tanpa disadari .Net framework sudah melakukannya: Secara bawaan, tanggal dan nomer sudah diformat berdasarkan aturan bawaan sistem komputer dimana kamu menjalankan aplikasi mu. Buruknya, perilaku bawaan ini mungkin tidak selalu apa yang kamu inginkan. Jangan khawatir - kamu dapat dengan mudah mengganti perilaku ini. Semua ini berhubungan dengan penggunaan kelas CultureInfo, yang dapat kamu baca dengan lebih lanjut di C# Artikel Tutorial CultureInfo. Untuk sekarang, mari kita bahas bagaimana cara menerapkan teknik-teknik tersebut di aplikasi WPF mu.

Pemformatan dasar

Jika kamu hanya perlu untuk memformat suatu bagian spesifik dari sebuah informasi, cth. isi dari sebuah kontrol Label, kamu dapat melakukan nya dengan sangat mudah, menggunakan kombinasi dari method ToString() dan class CultureInfo. Semisal, pada contoh di atas, aku menerapkan pemformatan berbasis budaya yang berbeda-beda seperti ini:

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);

Ini mungkin cukup untuk beberapa kasus, misalnya kamu hanya membutuhkan format spesial di beberapa tempat saja, tapi pada umumnya, kamu harus memutuskan apakah aplikasi mu harus menggunakan aturan sistem (bawaan) atau kamu harus merubah perilaku ini dengan aturan budaya yang spesifik untuk keseluruhan aplikasi.

CurrentCulture & CurrentUICulture

Applying another culture to your WPF application is quite easy. You will, potentially, be dealing with two attributes, found on the CurrentThread property of the Thread class: CurrentCulture and CurrentUICulture. But what's the difference?

The CurrentCulture property is the one that controls how numbers and dates etc. are formatted. The default value comes from the operating system of the computer executing the application and can be changed independently of the language used by their operating system. It is, for instance, very common for a person living in Germany to install Windows with English as their interface language, while still preferring German-notation for numbers and dates. For a situation like this, the CurrentCulture property would default to German.

The CurrentUICulture property specifies the language that the interface should use. This is only relevant if your application supports multiple languages, e.g. through the use of language-resource files. Once again, this allows you to use one culture for the language (e.g. English), while using another (e.g. German) when dealing with input/output of numbers, dates etc.

Changing the application Culture

With that in mind, you now have to decide whether to change the CurrentCulture and/or the CurrentUICulture. It can be done pretty much whenever you want, but it makes the most sense to do it when starting your application - otherwise, some output might already be generated with the default culture, before the switch. Here's an example where we change the Culture, as well as the UICulture, in the Application_Startup() event which can be used in the App.xaml.cs file of your WPF application:

private void Application_Startup(object sender, StartupEventArgs e)
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
}

Since we use the Thread class as well as the CultureInfo, don't forget to add the required namespaces to your file, if they are not already present:

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.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!