Рассмотрим следующее простое приложение 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. Это окно, в котором я изменяю эти настройки в разделе «Часы и регион» панели управления:
Теперь, если вы создадите таргетинг на версию 4.5.2 или более раннюю, она будет работать так, как ожидалось, и после фактического изменения настройки вы получите вывод, подобный этому:
Теперь, собрав версию 4.6 или более позднюю, вы получите что-то вроде этого:
Если вы ориентируетесь на 4.6 или более позднюю версию, независимо от того, сколько раз вы меняете регион числового формата, независимо от того, сколько раз вы вызываете ClearCachedData
, CurrentCulture не изменится...
Но ждать! Вещи становятся еще более странными... Если вы поместите приведенный выше код в консольное приложение (используя Console.WriteLine вместо, конечно), он будет работать независимо от того, какую структуру вы выбрали (4.5.2, 4.6, что угодно..), странно не Это? Вот почему я написал «Только WPF» в заголовке.. но я точно не знаю, происходит ли это на какой-либо другой платформе, кроме WPF.
В этой истории есть еще одна сумасшедшая вещь, так как я играл с этой проблемой со вчерашнего дня, я нашел хитрый способ заставить WPF или консольные приложения, ориентированные на 4.5.2 или ниже, работать неправильно, как и приложение, ориентированное на 4.6. и старше. Простая установка CultureInfo.DefaultThreadCurrentCulture
на что-либо отличное от нуля приведет к поломке.
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#, так как это язык, который я использую, хотя я считаю, что эта проблема не зависит от языка.
Switch.System.Globalization.NoAsyncCurrentCulture
, я подтверждаю, что переключатель был включен, вызвавAppContext.TryGetSwitch
. К сожалению, у меня не получилось... - person taquion   schedule 18.12.2018