65.9K
CodeProject 正在变化。 阅读更多。
Home

Silverlight 和应用程序全球化 - 转换器方法

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.11/5 (5投票s)

2009 年 9 月 3 日

CPOL

6分钟阅读

viewsIcon

36712

downloadIcon

247

Silverlight 和应用程序全球化 - 转换器方法

引言

通常需要自定义软件应用程序以支持多种文化和地区。这有助于不同地理位置的客户使用相同的应用程序,但其中的一些信息会根据当地文化或地区进行定制。例如,日期在不同地区或国家/地区的显示方式可能大相径庭。在本文中,我们将探讨使用转换器来全局化 Silverlight 应用程序部分的几种可能性。

区域设置 - 何处以及为何?

语言、日期和数字的格式取决于我们如何配置操作系统。通常,在 Windows 中,可以通过“控制面板设置”然后选择“区域和语言选项”来完成此设置。任何用户都可以更改区域设置(前提是网络管理员允许他们这样做)以满足自己的需求。

那么,当您的应用程序在两个不同的国家/地区下载并运行时会发生什么?德国用户可能喜欢以与法国用户完全不同的方式查看日期和数字(我所说的数字是指应用程序中显示的任何数值属性)。

转换器方法

为此,一种简单的方法是设计您的应用程序,使得每个日期(或数字)字段都通过一个方法传递,该方法会将此日期(或数字)格式化为该系统的区域设置(基本上是您在控制面板中设置的内容)。从 Silverlight 的角度来看,一种更简单(嗯,更简洁)的方法是设计您的 XAML,以便在为任何日期和数字属性进行绑定时,我们还将该值通过一个转换器传递。此转换器负责将我们的属性本地化到特定的系统区域设置。

在讨论了我在此实现过程中遇到的一些有趣问题之后,让我们快速看一些代码。

在我的示例中,我将一个文本块绑定到当前日期和时间。这将显示原始值。然后,我将另一个文本块绑定到用于前一个文本块的相同属性。但是,这次我将该值通过一个转换器(在我的示例中称为 DateConverter)传递。此转换器获取当前系统区域设置,然后将“转换后”的值显示在文本块中。有四个命令按钮,它们使用操作系统可识别的区域代码(如 en-USde-DE)来更改当前线程的区域设置。

XAML 看起来是这样的

<TextBlock Text="Date" Grid.Row="1" Grid.Column="0" FontWeight="Bold"/>
<TextBlock x:Name="CurrentDate" Text="{Binding Path=DateText}" Grid.Row="1" 
Grid.Column="1" HorizontalAlignment="Left"/>
<TextBlock Text="Converted Date" Grid.Row="1" Grid.Column="2" FontWeight="Bold"/>
<TextBlock x:Name="ParsedDate" Text="{Binding DateText,
Converter={StaticResource DateConverter}}" Grid.Row="1" Grid.Column="3"/>
<Button x:Name="French" Content="French" Grid.Row="2" Grid.Column="0" 
Height="25" Width="120" HorizontalAlignment="Left" Click="French_Click"/>
<Button x:Name="German" Content="German" Grid.Row="2" Grid.Column="1" 
Height="25" Width="120" HorizontalAlignment="Left" Click="German_Click"/>
<Button x:Name="EnglishUS" Content="English - US" Grid.Row="2" Grid.Column="2" 
Height="25" Width="120" HorizontalAlignment="Left" Click="EnglishUS_Click"/>
<Button x:Name="EnglishUK" Content="English - UK" Grid.Row="2" Grid.Column="3" 
Height="25" Width="120" HorizontalAlignment="Left" Click="EnglishUK_Click"/>

在浏览器中的显示效果如下:

这些按钮仅用于模拟我们将在控制面板的区域设置屏幕中进行的操作。

//This is to be done by changing regional system settings.
//But for the sample here, a command click makes this change.
private void EnglishUK_Click(object sender, System.Windows.RoutedEventArgs e) {
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
    LoadDate();
}

private void EnglishUS_Click(object sender, System.Windows.RoutedEventArgs e) {
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
    LoadDate();
}

private void German_Click(object sender, System.Windows.RoutedEventArgs e) {
    Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
    LoadDate();
}

private void French_Click(object sender, System.Windows.RoutedEventArgs e) {
    Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
    LoadDate();
}

转换器中的 convert 方法看起来是这样的

public object Convert(object value,
    Type targetType,
    object parameter,
    System.Globalization.CultureInfo culture) {
        DateTime date;
        culture = System.Globalization.CultureInfo.CurrentCulture;
        if (value != null && DateTime.TryParse(value.ToString(), out date)) {
            string strDate = string.Empty;
            strDate = date.ToString(culture.DateTimeFormat.ShortDatePattern.ToString());
            return strDate;
        }
        else {
            return string.Empty;}
        }
}

我们有一个 if–else 条件,以确保传递到转换器的值实际上是一个 DateTime 值,否则我们会遇到一些棘手的错误。接下来,我们需要注意我们使用的日期格式类型,即我们需要知道要在应用程序中显示短日期格式还是长日期格式。在此示例中,我使用了短日期格式。但是,Converter 构造函数中提供的参数对象可以轻松地用于使此功能更具可定制性。DateTimeToString() 方法为我们完成了大部分转换工作。

我还会快速讨论一下如何将日期方法用于数字。首先,我会将数字转换为十进制数(可以将 integer 传递给转换器),然后使用十进制数的 ToString() 方法和区域设置来格式化该十进制数。我的转换器代码看起来是这样的

Decimal decNumber = System.Convert.ToDecimal(value);
strNum = decNumber.ToString("N", culture);

同样,Converter 参数对象提供了进一步的定制机会,可以传入一些附加的格式化值,例如将值四舍五入到最近的十进制数的附加说明等。

也可以使用类似的原理创建货币转换器。

此方法实现的潜在问题

好了,现在让我们看看此类实现可能带来的一些潜在问题。

首先,如果您查看上面的 DateConverter,您会看到一行额外的代码,它将本地区域设置变量设置为 CultureInfo.CurrentCulture。为什么需要这样做?嗯,用户有可能(我这里说的是有可能)在应用程序启动更改区域设置。出于某种原因,当应用程序运行时区域设置发生更改时,转换器中的区域设置参数不会更新。然后,我们需要通过使用此方法强制将日期转换为新的区域设置。我猜测为什么一旦应用程序运行,转换器中的区域设置不会更新,是因为转换器只加载到内存一次,然后在区域设置更改时不会真正更新(毕竟,一个转换器由整个 Silverlight 应用程序共享,为什么还要一遍又一遍地加载到内存中呢?)。我没有找到任何正式文档对此进行说明,所以这只是纯粹的猜测。

此实现的另一个问题是,如果您需要将绑定值传递给另一个转换器进行其他处理(我们称之为新转换器 SomeOtherConverter)。嗯,在这种情况下,您可以在 SomeOtherConverter 中创建 DateConverter 的实例,然后将日期传递给它。至少,这可以将您的全局化/本地化处理集中在一个地方,使维护更容易。

每当我们通过这些区域设置转换器传递日期或数字时,我们必须记住,这些值会丢失其原始类型。DateTimeDecimal 值被转换为 String。如果您想在应用程序中绘制“贷款金额”与“客户姓名”之类的图表,并且希望以当前区域设置显示“贷款金额”,则此转换没有帮助。图表控件可能需要实际的数字作为“贷款金额”,并且在绘图最终完成时,在绘图之前将这些值转换为 string 可能会导致错误。

此方法是否可用于语言全球化?嗯,理论上,对于小型应用程序,您可以做到。想象一下,您的 XAML 中有许多“硬编码”的标题显示在文本块、列表框或其他控件中。而不是硬编码,我们可以绑定到语言转换器,并使用区域设置返回本地化语言的等效项。控件的名称可以通过转换器参数发送到转换器,只是为了允许我们维护一个单一的语言转换器。但是,正如您现在所猜到的,这可能不是一个好方法。我们可能应该坚持使用资源文件来支持 Silverlight 中的多种语言。

本文探讨了使用 Silverlight 转换器为日期和数字提供区域设置支持的方法。此外,还讨论了一些实现问题。

历史

  • 初次修订 - 2009 年 9 月 3 日
© . All rights reserved.