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

根据 CurrentCulture 进行绑定

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.73/5 (8投票s)

2015年6月29日

CPOL

4分钟阅读

viewsIcon

26495

根据 CurrentCulture 进行绑定

引言

关于这个问题,你可以在互联网上找到很多问题。 也有很多关于这个问题的答案 - 但哪个最好呢? 如果你理解这个问题,你可以简单地选择最好的一个。 我将尝试解释它内部是如何工作的。 首先,让我们定义一下绑定和值格式化方面的问题到底是什么。

如果你假设你的应用程序将在多语言环境中被使用,你希望根据地区习俗来格式化应用程序中的值。 此外,默认的地区格式化习俗可能被运行应用程序的计算机的用户修改。

在捷克环境中,将小数格式化为以下形式是很常见的:10 000,5。在英语国家,它将是:10,000.5。 尽管如此,可能有一个用户(也许是一个捷克程序员)希望使用英语格式,因此他在操作系统的“区域和语言”设置中将小数的默认格式更改为英语格式。 我们希望在我们的应用程序中尊重这些设置,也就是说,我们希望所有关心值格式化的机制都使用 CultureInfo.CurrentCulture static 属性 - 该属性保存用户设置。

逐步解决

如果你尝试将你的 View 绑定到你的 ViewModel 的属性(double 类型),你首先注意到的是(如果你不是来自英语国家),Binding 默认将小数格式化为英语习俗,如下面的简化 XAML 代码及其结果窗口所示。 请注意,窗口已将 DataContext 设置为 double 100.5

<Window>
   <TextBlock Text="{Binding}"/>
?</Window>

原因是绑定(其底层的转换机制)根据 FrameworkElement.Language 属性来格式化值。 此属性的默认值为“en-US”。 这里是第一个可能的解决方案,即如何使其根据 CultureInfo.CurrentCulture 格式化值。

因为此属性的值是可继承的,所以你可以在根元素 (Window) 上将 Language 属性的值设置为你想要的那个,并且将确保正确的格式化。

<Window Language="cs">
   <TextBlock Text="{Binding}"/>
?</Window>

现在你可以看到,该值按照捷克国家的习惯进行格式化。 但就我们的期望而言,这个解决方案仍然不够完美。

Language 属性的类型是 XmlLanguageXmlLanguage 的实例可以通过 static 方法 GetLanguage(string ietfLanguageTag) 来检索。 XmlLanguage 有一个方法 GetSpecificCulture() ,它返回一个 CultureInfo ,用于格式化,但 CultureInfo CultureInfo.CurrentCulture static 属性中的不同。 这是一个标准的 CultureInfo ,它对应于传递给 GetLanguage 方法的 ietfLanguageTag - 没有用户的格式化修改。

如果你将小数点分隔符设置为 #,你将看到它不会影响格式化的值。

最后一个 XAML 的结果窗口仍然是一样的,这不是我们想要的。

修改 Language 属性不是实现目标的正确方法。 别担心。 真正的解决方案确实存在。

Binding 有一个 ConverterCulture 属性,它的类型是 CultureInfo。 该属性的文档说

获取或设置用于评估转换器的文化。

如果你没有设置此属性,绑定引擎将使用绑定目标对象的 Language 属性。 在 XAML 中,这默认为“en-US”或从页面的根元素(或任何元素)继承该值(如果已显式设置)。

此属性的值作为其两个方法 Convert ConvertBack 的最后一个参数传递给 IValueConverter ,但此外,该参数也用于将值格式化为 string 和从 string 格式化。 正如文档中的文本所说,ConverterCulture 具有优先级。 因此,如果你想完全按照用户设置格式化你的值,请将你的 Binding ConverterCulture 设置为 CultureInfo.CurrentCulture

新的 XAML 文件和结果窗口将如下所示

<Window xmlns:globalization="clr-namespace:System.Globalization;assembly=mscorlib">
   <TextBlock Text="{Binding ConverterCulture={x:Static globalization:CultureInfo.CurrentCulture}}"/>
</Window>

这正是我们想要的。

如果你太懒(像我一样)在你的绑定中到处设置 ConverterCulture 属性,你可以使用以下类代替标准 Binding。

public class CustomBinding : System.Windows.Data.Binding
{
    public CustomBinding()
    {
        ConverterCulture = CultureInfo.CurrentCulture;
    }
?}

该类只做一件简单的事情。 它默认将 ConverterCulture 属性设置为  CultureInfo.CurrentCulture 。 这正是我们想要的,并且可以在任何使用标准 Binding 的地方使用。

类的用法很简单

<Window xmlns:wpfApplication="clr-namespace:WpfApplication">
   <TextBlock Text="{wpfApplication:CustomBinding}"/>
?</Window>

就这样。 我相信它会对你有所帮助。

© . All rights reserved.