CultureInfo.ClearCachedData 在 .net 4.6 及更早版本中无法正常工作,仅适用于 WPF

CultureInfo.ClearCachedData is not working properly in .net 4.6 and older for WPF only

考虑以下简单的 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}";
            };
        }

每次用户更改其区域设置时,它都会将旧文化的名称打印到 Old TextBlock,并且在调用 ClearCachedData 后,新文化的名称将设置在 New TextBlock 上。这是 window,我在控制面板的时钟和区域部分更改了这些设置:

现在,如果您构建的目标是 4.5.2 或更低版本,它将按预期工作,并且在实际更改设置后您将收到类似于以下内容的输出:

现在,针对 4.6 或更高版本构建,您会得到如下内容:

如果您的目标是 4.6 或更高版本,无论您更改多少次数字格式区域,无论您调用多少次 ClearCachedData,CurrentCulture 都不会更改...

但是等等!事情变得更奇怪了......如果你将上面的代码放入控制台应用程序(使用 Console.WriteLine 而不是当然),它的工作不依赖于你选择的框架(4.5.2、4.6,任何......),奇怪的是不是吗?这就是为什么我在标题中写了 "WPF only".. 但我不确定这是否发生在 WPF

以外的任何其他平台上

这个故事还有一个疯狂的事情,因为我从昨天开始就一直在研究这个问题,我发现了一种制作 WPF 或控制台应用程序的复杂方法,目标是 4.5.2 或以下,工作不正常,只是作为目标 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。所以,我认为针对 4.6 的 WPF 正在以某种方式设置 CultureInfo.DefaultThreadCurrentCulture,但在测试了这个理论之后我真的被卡住了,因为默认情况下它是 null,4.6 及更早版本中的事件...

那么,这是 WPF and/or .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 及更高版本。请注意,对 ClearCachedData 的调用仍然是必须的。我们创建一个新的线程实例,并手动将我们的 CurrentCulture 更新为新线程的 CurrentCulture。

编码愉快!