WPF 中本地化变得简单






2.33/5 (2投票s)
以声明式方式轻松本地化您的 WPF 应用程序。
引言
本文讨论了一种在WPF应用程序中轻松实现本地化的方法。
背景
在本文中,我将讨论WPF应用程序中的本地化。 XAML是声明性创建应用程序界面的绝佳工具,我们将使用这种声明性力量来利用.NET的全球化/本地化功能。 在设计此功能时,以下考虑因素至关重要
- 应用程序的本地化必须通过XAML以声明方式完成,无需后台代码
- XAML代码必须易于阅读和维护
- 必须支持运行时文化更改,以便应用程序无需重启即可进行文化更改 (注意:这可能不是您想要的功能。)
- 解决方案在内存和CPU时间方面都必须高效,因为操作是在UI线程上执行的
- 设计时体验不得改变,因此开发人员可以基于默认语言开发UI,而不必担心它在运行时如何本地化
参考文献
我从以下文章中汲取了灵感/想法
- 强制WPF重新绑定 -
http://beta.blogs.microsoft.co.il/blogs/alex_golesh/archive/2009/07/14/silverlight-quick-tip-how-to-force-re-binding.aspx - 在XAML和代码中使用资源文件进行本地化 -
http://windowsclient.net/learn/video.aspx?v=297139 - C# 中的弱引用 -
http://www.switchonthecode.com/tutorials/csharp-tutorial-weak-references
步骤1 – 创建本地化资源文件
第一步是创建保存本地化资源的资源文件。 我创建了一个WPF应用程序,在Property文件夹下,我打开了Resources.resx,并输入了一个string
,其键为“Hello
”,值为“Hello
”。 这是我的英语资源文件。 此外,最重要的是为该资源文件选择 访问修饰符为公共,否则XAML将无法访问它。
我还创建了另一个名为Resources.ru-RU.resx的资源文件,并将其添加到Property文件夹中。 在此资源文件中,我添加了一个string
,其键为“Hello
”,值为“????????????
”,这显然意味着俄语中的hello。 因此,根据不同的文化,应用程序应该选择正确的string
。 另请注意,在此资源文件中,访问修饰符设置为无代码生成。
步骤2 – 创建一个简单的窗口
接下来,我们创建一个简单的窗口,其中包含两个单选按钮,以便用户能够在英语和俄语之间切换文化,以及一个文本块,该文本块将显示来自正确资源字典的hello字符串。
要本地化一个控件,我们需要在该控件上设置一个名为Localization的附加属性。 此属性的类型为LocalizationInfo
,它有两个属性来支持本地化
Property
– 这是实际的DependencyProperty
,它应该在UI上显示本地化的值。 在我们的示例中,我们使用TextBlock.TextProperty
来实现此目的。ResourceKey
– 这是资源文件中的资源键。 在我们的例子中,这是“Hello
”。
这是窗口的XAML定义
<Window x:Class="Localization.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Localization"
xmlns:resources="clr-namespace:Localization.Properties"
Title="Window1" Height="300" Width="300">
<StackPanel ButtonBase.Click="OnLanguageChanged">
<RadioButton x:Name="EnglishButton" Content="English" IsChecked="True"/>
<RadioButton Content="Russian"/>
<TextBlock Text="{x:Static resources:Resources.Hello}">
<local:LocalizationManager.Localization>
<local:LocalizationInfo
Property="{x:Static TextBlock.TextProperty}"
ResourceKey="Hello"/>
</local:LocalizationManager.Localization>
</TextBlock>
</StackPanel>
</Window>
请注意粗体中的LocalizationInfo
属性,以及通过静态Resources.Hello
字段支持的设计时文本。 此外,单选按钮通过附加处理程序连接到OnLanguageChanged
方法
private void OnLanguageChanged(object sender, RoutedEventArgs e)
{
Thread.CurrentThread.CurrentUICulture =
new CultureInfo((bool)EnglishButton.IsChecked ? "en-US" : "ru-RU");
LocalizationManager.UpdateResources();
}
这一切是如何工作的?
跟踪可本地化UI元素并更新其内容的魔力在LocalizationManager
类中完成。 UpdateResources
是令人感兴趣的方法
/// <summary>
/// Updates the resources after a culture change has occurred
/// </summary>
public static void UpdateResources()
{
List<WeakReference> deadReferences = new List<WeakReference>();
foreach (WeakReference reference in Elements)
{
FrameworkElement element = reference.Target as FrameworkElement;
if (element != null)
{
LocalizationInfo localizationInfo = GetLocalization(element);
if (localizationInfo != null)
{
element.SetValue(localizationInfo.Property,
Resources.ResourceManager.GetString(
localizationInfo.ResourceKey,
Thread.CurrentThread.CurrentUICulture));
}
}
else
{
deadReferences.Add(reference);
}
}
foreach (WeakReference reference in deadReferences)
{
Elements.Remove(reference);
}
}
它基本上迭代可本地化的FrameworkElements
的HashSet
,并从本地化资源中更新DependencyProperty
的内容。 请注意,我们维护一个弱引用的HashSet
,因此UI元素仍然可以被垃圾回收,而无需我们持有引用。 作为一个清理阶段,我们检测无效的引用并将其从HashSet
中删除。 就这样! 现在您知道了如何使用最少的代码来本地化您的WPF应用程序!
历史
- 2010年2月17日:初始文章