首页 > 解决方案 > 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# 标记这个问题,因为它是我使用的语言,尽管我认为这个问题与语言无关。

标签: c#.netwpfcultureinfo.net-4.6

解决方案


对于那些可能会遇到同样问题的未来和未来的访客。我找到了一种解决方法:

    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 更新为新线程的实例。

快乐编码!


推荐阅读