为什么我不能在设计时在 XAML 中使用 CultureInfo.CurrentCulture?
Why can't I use CultureInfo.CurrentCulture in XAML at design time?
我有以下 XAML:
<TextBlock Text="{Binding Source={x:Static s:DateTime.Now}, StringFormat=Date: {0:dddd, MMMM dd}}"/>
s:DateTime.Now
和 xmlns: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.Now
和 CultureInfo.CurrentCulture
之间的区别,以及为什么其中一个有效而另一个无效。
我已经看到了同样的行为,最好的回应是将 CurrentCulture 和 CurrentUICulture 视为在设计时 不会 有用的东西,除非你设置它。
与许多其他 WPF 表示构造一样,有时您的视图模型或其他属性需要考虑设计时间,以便您的可视元素在 VS 设计器中按预期显示。例如,Galasoft MVVM 框架包括一个 IsDesignTime 属性。您可以使用它(或您自己的框架提供的任何内容)来特例 a 属性,如果 IsDesignTime 为真,则将其设置为适合显示的某个值。这很方便,例如,当您想查看将该区域性设置为其他语言时它的显示方式。
因此对于您的示例,假设您确实在使用 MVVM 类型的体系结构——您可能希望将 TextBlock 文本 属性 绑定到您自己的视图模型 属性,并具有 that 属性 参与确定当前 DateTime 和 CurrentCulture。
请注意:请记住,对于桌面应用程序上的 WPF,Window 或 UserControl 构造函数不会在设计时环境中执行——仅在运行时执行。在您意识到这一点之前,这可能会让人感到困惑。
不久前我遇到了同样的问题,我强烈建议使用这个 nugget packet 进行本地化。它非常容易使用。
https://www.nuget.org/packages/WpfLocalizeExtension/
示例程序集名称 = 应用程序
资源文件 = MainApplication.resx
Ressource1Key1 = 测试
如果您使用的是 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
}
我知道您没有要求解决方法,我无法回答您原来的问题。
我仍然想 post 我的解决方案,以防其他人(例如我)在寻找解决方法时偶然发现您的问题。
如果您在 CustomBinding class 中设置您的 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。
我有以下 XAML:
<TextBlock Text="{Binding Source={x:Static s:DateTime.Now}, StringFormat=Date: {0:dddd, MMMM dd}}"/>
s:DateTime.Now
和 xmlns: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.Now
和 CultureInfo.CurrentCulture
之间的区别,以及为什么其中一个有效而另一个无效。
我已经看到了同样的行为,最好的回应是将 CurrentCulture 和 CurrentUICulture 视为在设计时 不会 有用的东西,除非你设置它。 与许多其他 WPF 表示构造一样,有时您的视图模型或其他属性需要考虑设计时间,以便您的可视元素在 VS 设计器中按预期显示。例如,Galasoft MVVM 框架包括一个 IsDesignTime 属性。您可以使用它(或您自己的框架提供的任何内容)来特例 a 属性,如果 IsDesignTime 为真,则将其设置为适合显示的某个值。这很方便,例如,当您想查看将该区域性设置为其他语言时它的显示方式。
因此对于您的示例,假设您确实在使用 MVVM 类型的体系结构——您可能希望将 TextBlock 文本 属性 绑定到您自己的视图模型 属性,并具有 that 属性 参与确定当前 DateTime 和 CurrentCulture。
请注意:请记住,对于桌面应用程序上的 WPF,Window 或 UserControl 构造函数不会在设计时环境中执行——仅在运行时执行。在您意识到这一点之前,这可能会让人感到困惑。
不久前我遇到了同样的问题,我强烈建议使用这个 nugget packet 进行本地化。它非常容易使用。 https://www.nuget.org/packages/WpfLocalizeExtension/
示例程序集名称 = 应用程序
资源文件 = MainApplication.resx
Ressource1Key1 = 测试
如果您使用的是 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
}
我知道您没有要求解决方法,我无法回答您原来的问题。
我仍然想 post 我的解决方案,以防其他人(例如我)在寻找解决方法时偶然发现您的问题。
如果您在 CustomBinding class 中设置您的 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。