c# - CultureInfo.ClearCachedData 仅适用于 WPF 在 .net 4.6 及更早版本中无法正常工作
问题描述
考虑以下简单的 WPF 应用程序:
XAML(主窗口):
<StackPanel>
<TextBlock x:Name="Old"/>
<TextBlock x:Name="New"/>
</StackPanel>
代码隐藏:
public MainWindow()
{
InitializeComponent();
SystemEvents.UserPreferenceChanged += (sender, args) =>
{
Old.Text = $"Old culture name {CultureInfo.CurrentCulture.Name}";
CultureInfo.CurrentCulture.ClearCachedData();
New.Text = $"New culture name {CultureInfo.CurrentCulture.Name}";
};
}
每次用户更改他们的区域设置时,它都会将旧文化的名称打印到旧文本块,并且在调用之后ClearCachedData
,新文化的名称将被设置在新文本块上。这是我在控制面板的时钟和区域部分更改这些设置的窗口:
现在,如果您构建目标为 4.5.2 或更低版本,它将按预期工作,并且在实际更改设置后,您将收到类似于以下内容的输出:
现在,构建目标为 4.6 或更高版本,您会得到如下内容:
如果您的目标是4.6或更高版本,无论您更改数字格式区域多少次,无论您调用多少次ClearCachedData
,CurrentCulture都不会改变...
可是等等!事情变得更奇怪了...如果您将上面的代码放入控制台应用程序(当然使用 Console.WriteLine 而不是),它的工作原理与您选择的框架无关(4.5.2、4.6、任何东西..),奇怪不是它?这就是为什么我在标题中写了“仅 WPF”.. 但我不确定这是否发生在 WPF 以外的任何其他平台上
这个故事还有另一个疯狂的事情,因为我从昨天开始就一直在玩这个问题,我找到了一种巧妙的方法来制作针对 4.5.2 或更低版本的 WPF 或控制台应用程序,工作错误,就像针对 4.6 的那个一样和更老。简单地设置CultureInfo.DefaultThreadCurrentCulture
为与 null 不同的任何东西都会将事情分开。
public MainWindow()
{
InitializeComponent();
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CurrentCulture;
SystemEvents.UserPreferenceChanged += (sender, args) =>
{
Old.Text = $"Old culture name {CultureInfo.CurrentCulture.Name}";
CultureInfo.CurrentCulture.ClearCachedData();
New.Text = $"New culture name {CultureInfo.CurrentCulture.Name}";
};
}
上面的代码将表现得好像它是针对 4.6。所以,我认为 WPF 以 4.6 为目标CultureInfo.DefaultThreadCurrentCulture
是以某种方式设置的,但是在测试了这个理论之后,我真的被卡住了,因为它默认为空,4.6 和更早版本的事件......
那么,这是 WPF 和/或 .NET 4.6 中的错误吗?我无法找到报告的这一重大变化。
拜托,任何对此有所启发的东西都将不胜感激。另外,如果这是一个错误并且有人知道我可以在哪里报告它,请告诉我。
注意:我用 C# 标记这个问题,因为它是我使用的语言,尽管我认为这个问题与语言无关。
解决方案
对于那些可能会遇到同样问题的未来和未来的访客。我找到了一种解决方法:
public MainWindow()
{
InitializeComponent();
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CurrentCulture;
SystemEvents.UserPreferenceChanged += (sender, args) =>
{
Old.Text = $"Old culture name {CultureInfo.CurrentCulture.Name}";
CultureInfo.CurrentCulture.ClearCachedData();
CultureInfo.CurrentCulture = new Thread(() => { }).CurrentCulture;
New.Text = $"New culture name {CultureInfo.CurrentCulture.Name}";
};
}
上面的代码适用于两种构建选项:4.5.2 及更早版本,或 4.6 及更高版本。请注意,调用 toClearCachedData
仍然是必须的。我们创建一个新线程实例,然后手动将 CurrentCulture 更新为新线程的实例。
快乐编码!
推荐阅读
- mapping - 合同修改映射数据时web3js发送交易失败,但重新混合工作
- micronaut - Can you alter a Micronaut App features from the command line?
- c - 在导致分段错误的字符串文字上使用 strtol
- apache-spark - 如何在 Spark 数据帧上训练神经网络自动编码器(Keras)
- java - 应用主题在预览中显示,但在手机上不显示
- java - ZXing Android Embedded GS-1 支持
- python - 出现错误:无法读取 python selenium 中未定义的属性“单击”
- php - 在会话中编辑值
- php - Composer Yii2 Bower:要发布的文件或目录不存在:C:\myProject\vendor\bower/jquery/dist
- sql - 即使当天/周/月没有数据也返回结果