WinRT应用程序和区域设置。 根据用户的区域设置格式化日期和数字的正确方法?

关于用户的区域设置,我在Windows 8 Metro应用程序(XAML和C#)中遇到了一些问题。 似乎应用程序不会尊重用户的区域设置 ,因此即使您的Windows 8设置为以芬兰语格式显示日期和时间,应用程序仍将使用美国格式显示它们。 但这是一个很大的问题,必须有一些我缺少的东西?

为了测试这一点,我开始创建一个WPF应用程序 。 应用程序只打印出CurrentCulture和格式化的DateTime.Now:

private void Culture_Loaded_1(object sender, RoutedEventArgs e) { this.Culture.Text = System.Globalization.CultureInfo.CurrentCulture.DisplayName; } private void Date_Loaded_1(object sender, RoutedEventArgs e) { this.Date.Text = DateTime.Now.ToString(); } 

这是我的默认区域设置: 区域设置

运行时,应用程序以芬兰语格式显示日期:

芬兰格式

然后我将区域设置更改为美国: 美国区域设置

当应用程序再次运行时,文化和格式发生了变化: 美国wpf格式化

就像我期望一切正常工作,这也是我期望WinRT应用程序的工作方式。

因此,作为下一步,我使用相同的代码创建了一个WinRT(XAML&C#)应用程序,并将区域设置恢复为芬兰语。 问题:

Winrt格式化

即使我通过区域设置定义格式应为“芬兰语”,WinRT应用程序也会以美国格式显示日期时间。 然后我修改了应用程序的项目文件,并使fi-FI成为默认语言

默认语言

此更改还修改了应用程序的文化:

芬兰winrt格式

奇怪。 我将默认语言更改回其默认值,格式化已恢复为美国。 然后我在项目中创建了文件夹“Strings-fi-FI”,并在项目中添加了一个空的“Resources.resw” 。 这个空文件似乎已经足够了,因为我现在正在使用芬兰格式:

资源文件芬兰格式

只要删除空资源文件,格式就会恢复为US:

资源文件已删除美国格式winrt

很奇怪。

这导致几个问题,但我认为主要的问题是:WinRT应用程序是否故意不遵循用户的区域设置,如WPF应用程序?

已经有一段时间了,但这个问题还没有完全回答,所以让我分享一下我的小研究。 Depechie大多是对的,但他只提供了一个链接,并不是很确定。

是的,这种意想不到的变化是有意的。 我们不应再使用CultureInfo,因为它包含遗留代码,Microsoft希望我们使用Windows.Globalization API。

要获得当前区域,我们可以使用:

 GeographicRegion userRegion = new GeographicRegion(); string regionCode = userRegion.CodeTwoLetter; 

但是我注意到它只包含区域信息,所以没有语言代码。 要获得语言,我们可以使用:

 string langRegionCode = Windows.Globalization.Language.CurrentInputMethodLanguageTag; // depends on keyboard settings List langs = Windows.System.UserProfile.GlobalizationPreferences.Languages; // all user languages, like in languages control panel List applicationlangs = Windows.Globalization.ApplicationLanguages.Languages; // application languages (user languages resolved against languages declared as supported by application) 

如果语言有方言,它们会以格式语言-REGION返回BCP47语言标签,如果语言没有主要方言,则返回“pl”之类的语言。

我们还可以设置一种主要语言,它将覆盖所有其他语言:

 Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "en-US"; 

(这是一个持久化设置,应该在用户请求时使用)

还有新的日期,时间和数字API:

 Windows.Globalization.DateTimeFormatting.DateTimeFormatter dtf = new DateTimeFormatter("longdate", new[] { "en-US" }, "US", CalendarIdentifiers.Gregorian, ClockIdentifiers.TwentyFourHour); string longDate = dtf.Format(DateTime.Now); Windows.Globalization.NumberFormatting.DecimalFormatter deciamlFormatter = new DecimalFormatter(new string[] { "PL" }, "PL"); double d1 = (double)deciamlFormatter.ParseDouble("2,5"); // ParseDouble returns double?, not double 

Windows.Globalization API中确实有很多,但我认为这给了我们一般的想法。 进一步阅读:

您还可以在Windows 8开发人员中心论坛上找到一些有关该问题的主题以及一些Microsoft员工的答案,但他们主要将您发送到文档。

这是故意的。 微软正逐渐迫使应用程序采用操作系统语言。 相反,每个应用程序使用应用程序声明的信息(清单语言,在Windows.Globalization.ApplicationLanguages.ManifestLanguages中可观察)并由用户声明(用户语言,在Windows.System.UserProfile.GlobalizationPreferences.Languages中可观察)以确定如何显示资源和全球化的日期和时间。 这组语言称为应用程序语言(在Windows.Globalization.ApplicationLanguages.Languages中可观察)。 您看到的行为是因为您正在摆弄用户语言和清单语言,您将获得不同的应用程序语言。

难道我们现在需要查询其他类吗? 就像这里给出的例子一样: http : //code.msdn.microsoft.com/windowsapps/Globalization-preferences-6654eb36/sourcecode?fileId = 52104&pathId = 236099476

这篇文章似乎仍然相关,即使它是在两年前提出的。 我刚刚遇到它,因为我正在寻找关于同样事情的答案。 我还想在我的WP8.1 WinRT应用程序中以区域格式显示日期。 这里发布的信息有所帮助,但将它拼凑起来有点困难。

这就是我提出的,它似乎对我来说是我需要的答案:

 using Windows.Globalization; using Windows.Globalization.DateTimeFormatting; private string FormatDate(int year, int month, int day) { GeographicRegion userRegion = new GeographicRegion(); string regionCode = userRegion.CodeTwoLetter; var formatter = new DateTimeFormatter("year month day", new[] { regionCode }); DateTime dateToFormat = new DateTime(year, month, day); var formattedDate = formatter.Format(dateToFormat); return formattedDate; }