如果您在WPF应用程序中使用过一些数字或日期,例如 由于本教程中的一篇文章,您可能已经注意到一些很酷的东西:数字和日期会自动以与您计算机上使用的格式相匹配的格式显示。 如果你住在一个说英语的国家,这可能看起来不是什么大事,但如果你住在别的国家,日期和/或数字显示不同,这真的很酷。
如果你在想“格式化数字和日期之类的简单东西时会有那么多差异吗?”,我建议你看看这个示例应用程序,我在那里格式化了相同的数字和相同的日期 根据他们在美国,德国和瑞典的喜好:
正如您所看到的,数字和日期的显示方式存在许多细微差别。 好消息是.NET框架可以帮助你很多 - 事实上,它已经做了:默认情况下,日期和数字的格式是根据执行应用程序的计算机的系统设置。 坏消息是,这种行为可能并不总是你想要的。 但不要担心 - 你可以轻松改变这一点。 这一切都与CultureInfo类的使用有关,您可以在C#Tutorial的CultureInfo中阅读更多相关内容。 现在,让我们讨论如何将这些技术应用于您的WPF应用程序。
如果您只需要为特定信息应用格式,例如 单个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);
对于某些情况,这可能就足够了,您需要在几个地方进行特殊格式化,但一般情况下,您应该决定应用程序是否应该使用系统设置(默认设置),或者是否应该使用特定的区域性设置覆盖此行为 对于整个应用程序。
将另一种区域性应用于WPF应用程序非常简单。 您可能会处理Thread类的CurrentThread属性中的两个属性:CurrentCulture和CurrentUICulture。 但有什么区别?
CurrentCulture属性控制数字和日期等的格式。 默认值来自执行应用程序的计算机的操作系统,可以独立于其操作系统使用的语言进行更改。 例如,对于居住在德国的人来说,安装带有英语作为界面语言的Windows非常普遍,同时仍然更喜欢使用德语表示数字和日期。 对于这种情况,CurrentCulture属性将默认为德语。
CurrentUICulture属性指定界面应使用的语言。 这仅在您的应用程序支持多种语言时才有意义,例如: 通过使用语言资源文件。 再次,这允许您使用一种区域性语言(例如英语),在处理数字,日期等的输入/输出时使用另一个(例如德语)。
考虑到这一点,您现在必须决定是否更改CurrentCulture和/或CurrentUICulture。 它可以在任何时候完成,但在启动应用程序时最有意义 - 否则,在切换之前,某些输出可能已经使用默认区域性生成。 这是一个示例,我们在Application_Startup()事件中更改Culture和UICulture,它可以在WPF应用程序的App.xaml.cs文件中使用:
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 System.Threading;
using System.Globalization;
有了这个,数字和日期现在将根据他们在德语(de-DE)中的喜好来格式化。 如上所述,如果您的应用程序不支持多种语言,您可以省略定义CurrentUICulture的行(最后一行)。
在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,然后更新包含数字和日期的两个标签:
如果您的应用程序使用多个线程,则应考虑使用DefaultThreadCurrentCulture属性。 它可以在CultureInfo类(在.NET框架版本4.5中引入)中找到,并且将确保不仅当前线程,而且未来线程将使用相同的区域性。 您可以像这样使用它,例如 在Application_Startup事件中:
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de-DE");
那么,您是否必须同时设置CurrentCulture和DefaultThreadCurrentCulture属性? 实际上,不 - 如果您尚未更改CurrentCulture属性,则设置DefaultThreadCurrentCulture属性也将应用于CurrentCulture属性。 换句话说,如果您计划在应用程序中使用多个线程,则使用DefaultThreadCurrentCulture而不是CurrentCulture是有意义的 - 它将负责所有场景。
处理WPF应用程序的区域性非常重要,但幸运的是,WPF将为您提供完全开箱即用的功能。 如果您需要更改默认行为,那么使用CurrentCulture和CurrentUICulture属性也很容易,如本文的众多示例所示。