为什么在XAML设计时不能使用CultureInfo.CurrentCulture?

8

我有以下的 XAML 代码:

<TextBlock Text="{Binding Source={x:Static s:DateTime.Now}, StringFormat=Date: {0:dddd, MMMM dd}}"/>

s:DateTime.Nowxmlns:s="clr-namespace:System;assembly=mscorlib" 在运行时和设计模式(Visual Studio 2015 Enterprise)中都可以正常工作。

但是如果我尝试使用 CultureInfo.CurrentCulture,那么这只在运行时工作,并在设计模式中给出错误信息 (xmlns:c="clr-namespace:System.Globalization;assembly=mscorlib"):

<TextBlock Text="{Binding Source={x:Static s:DateTime.Now}, ConverterCulture={x:Static c:CultureInfo.CurrentCulture}, StringFormat=Date: {0:dddd, MMMM dd}}"/>

我不是在寻找解决方法。我只是想了解DateTime.NowCultureInfo.CurrentCulture之间的区别,以及为什么其中一个可以工作而另一个不能。


3
它给你什么错误?你确定差别是在于DateTime.NowCultureInfo.CurrentCulture,而不是在于SourceConverterCulture之间吗?(尽管可能很奇怪,试着将Source指定为CultureInfo.CurrentCulture,看看是否还会出错。) - Jon Skeet
3
我在我的设备上重现了这个问题。我也尝试了@JonSkeet建议的方法,问题确实在于“CurrentCulture”。顺便提一下,“CurrentCulture”的文档中写道:“表示当前线程使用的区域设置的对象。” 这不是问题吗? 因为在设计时没有“当前线程”。 “DefaultThreadCurrentCulture”、“InstalledUICulture”、“InvariantCulture”和“DefaultThreadCurrentUICulture”都可以正常工作。只有“CurrentCulture”和“CurrentUICulture”出现了问题。 - Szabolcs Dézsi
3个回答

3

我知道你没有要求解决方法,也无法回答你原来的问题。

但我仍然想发布我的解决方案,以防像我一样的其他人在寻找解决方法时偶然发现了你的问题。

如果您在CustomBinding类中设置ConverterCulture,并在xaml中使用此CustomBinding而不是Binding,则它也可以在设计时间正常工作。

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

你可以像这样在你的xaml中使用它。
<TextBlock Text="{CultureAwareBinding Source={x:Static s:DateTime.Now}, StringFormat=Date: {0:dddd, MMMM dd}}"/>

作为额外的好处,这样做可以让您在需要时仅在一个地方更改ConverterCulture。此外,您还可以像这样设置其他属性,例如StringFormat。

虽然这确实没有回答我的问题,但它仍然是最好的答案。我已经尝试过了,它有效。谢谢! - Kim Homann

0
我曾经遇到过这种情况,最好的解决方法是将CurrentCulture和CurrentUICulture视为设计时不可用,除非你设置它。
与许多其他WPF演示结构一样,有时候你的视图模型或其他属性需要考虑设计时,以便你的视觉元素在VS设计器中按预期显示。例如,Galasoft MVVM框架包括一个IsDesignTime属性。你可以使用它(或你自己的框架提供的任何内容)来特殊处理一个属性,如果IsDesignTime为true,则将其设置为适合显示的某个值。这很方便,例如当你想看看将该文化设置为其他语言时它是如何显示的。
因此,对于你的例子,假设你确实使用了MVVM类型的架构——你可能希望将你的TextBlock Text属性绑定到你自己的视图模型属性,并让那个属性确定当前DateTime和CurrentCulture。
一个注意点:请记住,在桌面应用程序上使用WPF时,Window或UserControl构造函数不会在设计时环境中执行——只有在运行时才会执行。在你意识到这一点之前,这可能会让人感到困惑。

0
我不久前也遇到了同样的问题,我强烈建议使用这个本地化的nugget包。它非常容易使用。 https://www.nuget.org/packages/WpfLocalizeExtension/ 例如: AssemblyName = Application
RessourceFile = MainApplication.resx
Ressource1Key1 = Test
如果您正在使用MVVM,这里有一些代码片段。
XAML
    xmlns:lex="http://wpflocalizeextension.codeplex.com"
    lex:LocalizeDictionary.DesignCulture="en"
    lex:ResxLocalizationProvider.DefaultAssembly="AssemblyName"
    lex:ResxLocalizationProvider.DefaultDictionary="ressourceName"

定义标签、按钮等的内容...

<Label Content="{lex:Loc AssemblyName:ResourceName:ResourceKey}">
<Label Content="{lex:Loc Application:MainApplication:Test}">

在 ViewModel 中,您想将按钮绑定到命令 FrenchUI、EnglishUI。

private void FrenchUI()
    {
        LocalizeDictionary.Instance.SetCurrentThreadCulture = true;
        LocalizeDictionary.Instance.Culture = new CultureInfo(ConfigurationManager.AppSettings["Culture"])//fr-CA;
    }

    private void EnglishUI()
    {
        LocalizeDictionary.Instance.SetCurrentThreadCulture = true;
        LocalizeDictionary.Instance.Culture = new CultureInfo(ConfigurationManager.AppSettings["CultureUS"]);//en-US
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接