- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Windows 7 区域和语言对话框中的各种设置为 CurrentCulture 对象的属性提供值。然而,WPF控件似乎改用CurrentUICulture,导致完全无法尊重用户的偏好。
例如,在我的工作站上,WPF 控件似乎使用 en-US 的 CurrentUICulture,导致它们以美国格式 M/d/yyyy 显示日期,而不是在“区域和语言”对话框中指定的澳大利亚格式。
在数据绑定(bind)中显式指定 en-AU 区域性会导致相关控件使用默认的澳大利亚格式,但它继续忽略用户指定的格式。这很奇怪;进入应用程序我验证了 DateTimeFormatInfo.CurrentInfo == Thread.CurrentThread.CurrentCulture.DateTimeFormat (同一对象)和 DateTimeFormatInfo.CurrentInfo.ShortDatePattern == "yyyy-MM-dd"(我设置的值,以便我可以确定用户首选项是否或正在采用默认值)。一切都如预期,因此从表面上看,最大的问题是如何说服 WPF 控件和数据绑定(bind)使用 CurrentCulture 而不是 CurrentUICulture。
我们应该如何让 WPF 应用程序尊重区域和语言设置?
<小时/>基于 Sphinxx 的答案,我重写了 Binding 类的两个构造函数,以提供与标准标记更完整的兼容性。
using System.Globalization;
using System.Windows.Data;
namespace ScriptedRoutePlayback
{
public class Bind : Binding
{
public Bind()
{
ConverterCulture = CultureInfo.CurrentCulture;
}
public Bind(string path) : base(path)
{
ConverterCulture = CultureInfo.CurrentCulture;
}
}
}
<小时/>
进一步的实验表明,您可以使用 x:Static 在标记中引用 System.Globalization.CultureInfo.CurrentCulture。这在运行时是完全成功的,但在设计时却是一场灾难,因为绑定(bind)编辑器不断删除它。更好的解决方案是使用辅助类来遍历窗口的 DOM 并修复它找到的每个 Binding 的 ConverterCulture。
using System;
using System.Windows;
using System.Windows.Data;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
namespace ScriptedRoutePlayback
{
public static class DependencyHelper
{
static Attribute[] __attrsForDP = new Attribute[] { new PropertyFilterAttribute(PropertyFilterOptions.SetValues | PropertyFilterOptions.UnsetValues | PropertyFilterOptions.Valid) };
public static IList<DependencyProperty> GetProperties(Object element, bool isAttached = false)
{
if (element == null) throw new ArgumentNullException("element");
List<DependencyProperty> properties = new List<DependencyProperty>();
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(element, __attrsForDP))
{
DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(pd);
if (dpd != null && dpd.IsAttached == isAttached)
{
properties.Add(dpd.DependencyProperty);
}
}
return properties;
}
public static IEnumerable<Binding> EnumerateBindings(DependencyObject dependencyObject)
{
if (dependencyObject == null) throw new ArgumentNullException("dependencyObject");
LocalValueEnumerator lve = dependencyObject.GetLocalValueEnumerator();
while (lve.MoveNext())
{
LocalValueEntry entry = lve.Current;
if (BindingOperations.IsDataBound(dependencyObject, entry.Property))
{
Binding binding = (entry.Value as BindingExpression).ParentBinding;
yield return binding;
}
}
}
/// <summary>
/// Use in the constructor of each Window, after initialisation.
/// Pass "this" as the dependency object and omit other parameters to have
/// all the bindings in the window updated to respect user customisations
/// of regional settings. If you want a specific culture then you can pass
/// values to recurse and cultureInfo. Setting recurse to false allows you
/// to update the bindings on a single dependency object.
/// </summary>
/// <param name="dependencyObject">Root dependency object for binding change treewalk</param>
/// <param name="recurse">A value of true causes processing of child dependency objects</param>
/// <param name="cultureInfo">Defaults to user customisations of regional settings</param>
public static void FixBindingCultures(DependencyObject dependencyObject, bool recurse = true, CultureInfo cultureInfo = null)
{
if (dependencyObject == null) throw new ArgumentNullException("dependencyObject");
try
{
foreach (object child in LogicalTreeHelper.GetChildren(dependencyObject))
{
if (child is DependencyObject)
{
//may have bound properties
DependencyObject childDependencyObject = child as DependencyObject;
var dProps = DependencyHelper.GetProperties(childDependencyObject);
foreach (DependencyProperty dependencyProperty in dProps)
RegenerateBinding(childDependencyObject, dependencyProperty, cultureInfo);
//may have children
if (recurse)
FixBindingCultures(childDependencyObject, recurse, cultureInfo);
}
}
}
catch (Exception ex)
{
Trace.TraceError(ex.Message);
}
}
public static void RegenerateBinding(DependencyObject dependencyObject, DependencyProperty dependencyProperty, CultureInfo cultureInfo = null)
{
Binding oldBinding = BindingOperations.GetBinding(dependencyObject, dependencyProperty);
if (oldBinding != null)
try
{
//Bindings cannot be changed after they are used.
//But they can be regenerated with changes.
Binding newBinding = new Binding()
{
Converter = oldBinding.Converter,
ConverterCulture = cultureInfo ?? CultureInfo.CurrentCulture,
ConverterParameter = oldBinding.ConverterParameter,
FallbackValue = oldBinding.FallbackValue,
IsAsync = oldBinding.IsAsync,
Mode = oldBinding.Mode,
NotifyOnSourceUpdated = oldBinding.NotifyOnSourceUpdated,
NotifyOnTargetUpdated = oldBinding.NotifyOnValidationError,
Path = oldBinding.Path,
StringFormat = oldBinding.StringFormat,
TargetNullValue = oldBinding.TargetNullValue,
UpdateSourceExceptionFilter = oldBinding.UpdateSourceExceptionFilter,
UpdateSourceTrigger = oldBinding.UpdateSourceTrigger,
ValidatesOnDataErrors = oldBinding.ValidatesOnDataErrors,
ValidatesOnExceptions = oldBinding.ValidatesOnExceptions,
XPath = oldBinding.XPath
};
//set only one of ElementName, RelativeSource, Source
if (oldBinding.ElementName != null)
newBinding.ElementName = oldBinding.ElementName;
else if (oldBinding.RelativeSource != null)
newBinding.Source = oldBinding.Source;
else
newBinding.RelativeSource = oldBinding.RelativeSource;
BindingOperations.ClearBinding(dependencyObject, dependencyProperty);
BindingOperations.SetBinding(dependencyObject, dependencyProperty, newBinding);
}
catch (Exception ex)
{
Trace.TraceError(ex.Message);
}
}
}
}
最佳答案
This SO post (WPF/Silverlight) 具有指向 this article 的链接(仅限 WPF),解释如何使用 CurrentCulture 作为应用程序的默认值。这能解决您的问题吗?
编辑:
使绑定(bind)使用“区域和语言”中的自定义设置而不是当前语言的默认设置需要更多技巧。 This post结论是,每个绑定(bind)的 ConverterCulture
也必须显式设置为 CultureInfo.CurrentCulture
。以下是一些日期时间测试:
<!-- Culture-aware(?) bindings -->
<StackPanel DataContext="{Binding Source={x:Static sys:DateTime.Now}}" >
<!-- WPF's default en-US formatting (regardless of any culture/language settings) -->
<TextBlock Text="{Binding Path=.}" />
<!-- *Default* norwegian settings (dd.MM.YYY) -->
<TextBlock Text="{Binding Path=., ConverterCulture=nb-NO}" />
<!-- Norwegian settings from the "Region and Languague" dialog (d.M.YY) -->
<TextBlock Text="{Binding Path=., ConverterCulture={x:Static sysglb:CultureInfo.CurrentCulture}}" />
<!-- Hiding ConverterCulture initialization in our own custom Binding class as suggested here:
https://stackoverflow.com/questions/5831455/use-real-cultureinfo-currentculture-in-wpf-binding-not-cultureinfo-from-ietfl#5937477 -->
<TextBlock Text="{local:CultureAwareBinding Path=.}" />
</StackPanel>
自定义绑定(bind)类:
public class CultureAwareBinding : Binding
{
public CultureAwareBinding()
{
this.ConverterCulture = System.Globalization.CultureInfo.CurrentCulture;
}
}
在挪威机器上,这一切最终看起来像这样:
关于wpf - CurrentUICulture 忽略区域和语言设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14149978/
在 .NET 应用程序中,您似乎可以通过以下方式获取或设置当前 (UI) 区域性 System.Threading.Thread.CurrentThread.CurrentUICulture 或通过
Windows 7 区域和语言对话框中的各种设置为 CurrentCulture 对象的属性提供值。然而,WPF控件似乎改用CurrentUICulture,导致完全无法尊重用户的偏好。 例如,在我的
我正在使用 CurrentUICulture 进行本地化。在不同的线程中查询 UI Culture 之前,这工作得很好。所以我的问题是如何修复 CurrentUICulture 以便在我创建新线程时它
我正在尝试更改我的 WPF 应用程序在点击事件中使用的语言,但它没有改变。 private void menuItemGerman_Click(object sender, RoutedEventAr
我有一个 asp.net mvc 应用程序,我希望用户能够更改语言。我提供了一系列带有小标志的链接,让用户选择语言。所有这些链接的目标是我的“仪表板”页面,其中 Controller 有以下代码: [
我的 MVC 项目中有以下两个文件: 我像这样在我的 global.asax 中设置文化: Thread.CurrentThread.CurrentUICulture = new CultureInf
我一直在搜索如何更改具有 Localizable 的表单的语言属性设置为 true。 https://msdn.microsoft.com/en-us/library/system.threading
据我了解,默认情况下,报表查看器的语言由 "CultureInfo.InstalledUICulture" 设置(不是那么简单)。这意味着,如果我的计算机来自巴西,那么它将使用巴西的文化来格式化数字。
我正在尝试找出程序的语言并为该语言更改我的字符串 CultureInfo culture = new CultureInfo("en"); CultureInfo currentCulture = T
我正在使用 C# 开发 SL5 应用程序,我希望将其国际化。我发现以下设置 UI 文化: var culture = new CultureInfo(Thread.CurrentThread.Curr
我试图在运行时设置应用程序的 CurrentUICulture。但是,我的表单中的菜单项保持不变。除了更改 CurrentUICulture 之外,我还需要做一些额外的事情吗? 最佳答案 聚会又迟到了
我有一个使用 .NET 3.5 框架的基于 WinForms 的应用程序。该应用程序具有某些资源的本地化版本。 当我在运行 Windows XP 副本的机器上运行该应用程序时,该副本最初安装时使用 e
我正在阅读一个资源,它说: CurrentUICulture must be set at the startup of a application. 对于 ASP.NET 网页,我应该在哪里适本地设
我正在用两种语言开发一个多语言网站,从阿拉伯语和英语开始 我已经在 IE 和 FireFox 中将语言设置为阿拉伯语 (ar-ae),但它总是给我英语版本,我无法解决这个问题 网站结构 Default
所以,我有一些本地化的资源文件。它们是可以格式化的字符串。 例如: MyResource.resx Title: "MyApp - Ver: {0}" 然后我这样返回它: public String
我正在一个小型测试 WPF 应用程序中进行本地化,并且想要英语和法语。我创建了 Resources.en-CA.resx 和 Resources.fr-CA.resx。 当我的测试应用程序启动时,我有
我正在尝试让我的应用程序支持多种语言。例如,我制作了一些附属程序集,现在我想测试应用程序在法国机器上运行时的外观。 在[控制面板->区域和语言选项]中,我可以在区域选项选项卡中选择法语(法国),在高级
CurrentCulture有什么区别, InvariantCulture , CurrentUICulture和 InstalledUICulture来自 System.Globalization.
我使用 .NET 3.5(网站项目)在 ASP.NET 中编写了页面。 我想使用 jQuery 添加一些特定于文化的验证器到我的页面。 我受伤了关于使用 Globalize 插件的很好的教程:http
我正在处理一个 ASP.NET Web API 项目,在该项目中我遇到了一个问题,其中子项 Task异步运行的 s 不继承父线程的当前文化;即,即使在设置了 Thread.CurrentThread.
我是一名优秀的程序员,十分优秀!