65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF 中本地化变得简单

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.33/5 (2投票s)

2010年2月18日

CPOL

3分钟阅读

viewsIcon

25613

downloadIcon

349

以声明式方式轻松本地化您的 WPF 应用程序。

引言

本文讨论了一种在WPF应用程序中轻松实现本地化的方法。

背景

在本文中,我将讨论WPF应用程序中的本地化。 XAML是声明性创建应用程序界面的绝佳工具,我们将使用这种声明性力量来利用.NET的全球化/本地化功能。 在设计此功能时,以下考虑因素至关重要

  1. 应用程序的本地化必须通过XAML以声明方式完成,无需后台代码
  2. XAML代码必须易于阅读和维护
  3. 必须支持运行时文化更改,以便应用程序无需重启即可进行文化更改 (注意:这可能不是您想要的功能。)
  4. 解决方案在内存和CPU时间方面都必须高效,因为操作是在UI线程上执行的
  5. 设计时体验不得改变,因此开发人员可以基于默认语言开发UI,而不必担心它在运行时如何本地化

参考文献

我从以下文章中汲取了灵感/想法

步骤1 – 创建本地化资源文件

第一步是创建保存本地化资源的资源文件。 我创建了一个WPF应用程序,在Property文件夹下,我打开了Resources.resx,并输入了一个string,其键为“Hello”,值为“Hello”。 这是我的英语资源文件。 此外,最重要的是为该资源文件选择 访问修饰符为公共,否则XAML将无法访问它。

我还创建了另一个名为Resources.ru-RU.resx的资源文件,并将其添加到Property文件夹中。 在此资源文件中,我添加了一个string,其键为“Hello”,值为“????????????”,这显然意味着俄语中的hello。 因此,根据不同的文化,应用程序应该选择正确的string。 另请注意,在此资源文件中,访问修饰符设置为无代码生成

步骤2 – 创建一个简单的窗口

接下来,我们创建一个简单的窗口,其中包含两个单选按钮,以便用户能够在英语和俄语之间切换文化,以及一个文本块,该文本块将显示来自正确资源字典的hello字符串。

要本地化一个控件,我们需要在该控件上设置一个名为Localization的附加属性。 此属性的类型为LocalizationInfo,它有两个属性来支持本地化

  1. Property – 这是实际的DependencyProperty,它应该在UI上显示本地化的值。 在我们的示例中,我们使用TextBlock.TextProperty来实现此目的。
  2. 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); 
    } 
}  

它基本上迭代可本地化的FrameworkElementsHashSet,并从本地化资源中更新DependencyProperty的内容。 请注意,我们维护一个弱引用的HashSet,因此UI元素仍然可以被垃圾回收,而无需我们持有引用。 作为一个清理阶段,我们检测无效的引用并将其从HashSet中删除。 就这样! 现在您知道了如何使用最少的代码来本地化您的WPF应用程序!

历史

  • 2010年2月17日:初始文章 
© . All rights reserved.