Metro插件系统系列就暂时停一下,这次我们讨论一下WPF的资源本地化实现,主要用到的:CultureInfo,ResourceManger,MarkupExtension,RESX文件,这些都是.NET框架提供的。

项目结构:

运行结果:

可在程序运行时,实时切换语言

CultureInfo

  CultureInfo类表示有关特定区域性的信息,包括区域性的名称、书写体系和使用的日历,以及有关对常用操作(如格式化日期和排序字符串)提供信息的区域性特定对象的访问。CultureInfo类的实例化一般有两个途径,如下所示: CultureInfo culture = CultureInfo. CreateSpecificCulture (name); CultureInfo culture = new CultureInfo(name);

二者的区别是,使用第一种方法,只能创建固定区域性或特定区域性的CultureInfo实例。如果name为空字符串,则建立固定区域性的实例,如果name为非特定区域性,那么建立name 关联的默认特定区域性的 CultureInfo实例。第二种方法,则是建立一个name所指定的区域性的CultureInfo实例,它可以是固定的,非特定的或特定区域性的。

Thread类的CurrentCulture属性用来获取或设置当前线程的区域性。它必须被设置为特定区域性。 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");如果Thread.CurrentThread.CurrentCulture = new CultureInfo("en ");就会报错!

Thread类的CurrentUICulture属性用来获取或设置资源管理器使用的当前区域性以便在运行时查找区域性特定的资源。

ResourceManger

  ResourceManger类可以查找区域性特定的资源,当本地化资源不存在时提供代用资源,并支持资源序列化。常用的ResourceManager的构造函数是public ResourceManager(string,Assembly)。其含义是初始化 ResourceManager类的新实例,它使用指定的根名称从给定的Assembly中查找资源文件。所谓根名称是例如名为“MyResource.en-US.resources”的资源文件的根名称为“MyResource”。在根名称的表达中可以加上命名空间,如“MyWebSite.Resource.UserFolder. MyResource”。而Assembly可以是需要调用资源文件的页面所在的Assembly,如typeof(MyPage).Assembly。ResourceManager类的GetString方法用来获得资源文件中的指定键的值。举例:当已设置了线程的CurrentUICulture属性之后按如下方法。 ResourceManager rm = new ResourceManager("items", Assembly.GetExecutingAssembly()); String str = rm.GetString("welcome");

如果想按照指定的区域性来获得资源则按照如下写法: ResourceManager rm = new ResourceManager("items", Assembly.GetExecutingAssembly()); CultureInfo ci = Thread.CurrentThread.CurrentCulture; String str = rm.GetString("welcome",ci);

MarkupExtension

  Markup Extensions 与TypeConverter 差不多,允许扩展Xaml表达式,把Xaml中的文本转换成相应的对象/对象程序。

在上述例子中,x:Null, x:Static, Binding 都是Markup Extension.
微软已经提供了相当多的扩展,并且我们还可以自定义扩展类型。
----------------------------------------------------------------------------------------------------

微软定义的Markup Extension
所有的Extensions都必须派生于:

publicabstractclass MarkupExtension { publicabstractobject ProvideValue(IServiceProvider serviceProvider); }

特定于 WPF 的标记扩展 WPF 编程中最常用的标记扩展是支持资源引用的标记扩展(StaticResource 和 DynamicResource)以及支持数据绑定的标记扩展 (Binding)。

1. StaticResource 通过替换已定义资源的值来为 XAML 属性提供值。

2. DynamicResource 通过将值推迟为对资源的运行时引用来为 XAML 属性提供值。动态资源引用强制在每次访问此类资源时都重新进行查找。

3. Binding 按应用于元素的数据上下文来为属性提供数据绑定值。此标记扩展相对复杂,因为它会启用大量内联语法来指定数据绑定。

4. RelativeSource 为可以在运行时元素树中定位若干可能关系的 Binding 提供源信息。对于在多用途模板中创建的绑定,或在未充分了解周围的元素树的情况下以代码创建的绑定,上述标记扩展会提供专用源。

5. TemplateBinding,控件模板可以通过它使用来自要利用该模板的类的对象模型定义属性中的模板化属性的值。有关详细信息,请参见 TemplateBinding 标记扩展。

XAML 定义的标记扩展

  有几个标记扩展并非是 XAML 的 WPF 应用程序所特有的,而是属于 XAML 语言的规范和命名空间的一部分。它们通常由语法中的 x: 前缀标识,如您在常见用法中所见到的一样。这些标记扩展的 WPF 实现使用相同的 MarkupExtension 基类来提供实现。

x:Type 为命名类型提供 Type 对象。此标记扩展最常用于样式和模板。 x:Static 从不直接属于属性值类型、但可以计算为该类型的值类型代码实体中生成静态值。 x:Null 将 null 指定为 XAML 属性的值。 x:Array: 在特意不使用基元素和控件模型提供的集合支持的情况下,x:Array 为 XAML 语法中常规数组的创建提供支持。

StringResourceExtension

//=================================================================================
//
// Copyright (C) 20013-2014
// All rights reserved
//
// description : 本文博客园首发,如果您想转载本博客,请注明出处,感谢支持
// created by Zengg
// http://www.cnblogs.com/01codeworld/
// Email:281365330@qq.com
//==================================================================================
namespace MultilanguageTest
{
[MarkupExtensionReturnType(typeof(BindingExpression))]
public class StringResourceExtension : MarkupExtension, INotifyPropertyChanged
{
/// <summary>
/// 资源的名称,与资源文件StringResource.resx对应
/// </summary>
[ConstructorArgument("key")]
public string Key
{
get;
set;
}
string _DefaultValue;
/// <summary>
/// 默认值,为了使在设计器的情况时把默认值绑到设计器
/// </summary>
public string DefaultValue
{
get
{
return _DefaultValue;
}
set
{
_DefaultValue = value;
}
}
string _Value;
/// <summary>
/// 资源的具体内容,通过资源名称也就是上面的Key找到对应内容
/// </summary>
public string Value
{
get
{
///如果为设计器模式,本地的资源没有实例化,我们不能从资源文件得到内容,所以从KEY或默认值绑定到设计器去
if (GlobalClass.InDesignMode)
{
if (Key != null && DefaultValue != null)
return DefaultValue;
if (Key == null && DefaultValue != null)
return DefaultValue;
if (Key != null && DefaultValue == null)
return Key;
if (Key == null && DefaultValue == null)
return "NULL";
}
else
{
if (Key != null)
{
string strResault=null ;
try
{
strResault = GlobalClass.GetString(Key);
}
catch
{
}
if (strResault == null)
{
strResault = _DefaultValue;
}
return strResault;
}
}
return _Value;
}
set
{
_Value = value;
}
}
public StringResourceExtension(string key)
: this()
{
Key = key;
GlobalClass.LanguageChangeEvent += new EventHandler<EventArgs>(Language_Event);
}
public StringResourceExtension(string key, string DefaultValue)
: this()
{
Key = key;
_DefaultValue = DefaultValue;
GlobalClass.LanguageChangeEvent += new EventHandler<EventArgs>(Language_Event); }
public StringResourceExtension()
{
}
/// <summary>
/// 每一标记扩展实现的 ProvideValue 方法能在可提供上下文的运行时使用 IServiceProvider。然后会查询此 IServiceProvider 以获取传递信息的特定服务
///当 XAML 处理器在处理一个类型节点和成员值,且该成员值是标记扩展时,它将调用该标记扩展的 ProvideValue 方法并将结果写入到对象关系图或序列化流,XAML 对象编写器将服务环境通过 serviceProvider 参数传递到每个此类实现。
/// </summary>
/// <param name="serviceProvider"></param>
/// <returns></returns>
public override object ProvideValue(IServiceProvider serviceProvider)
{
IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; Setter setter = target.TargetObject as Setter;
if (setter != null)
{
return new Binding("Value") { Source = this, Mode = BindingMode.OneWay };
}
else
{
Binding binding = new Binding("Value") { Source = this, Mode = BindingMode.OneWay };
return binding.ProvideValue(serviceProvider);
}
}
public event PropertyChangedEventHandler PropertyChanged; static readonly System.ComponentModel.PropertyChangedEventArgs
valueChangedEventArgs = new System.ComponentModel.PropertyChangedEventArgs("Value"); protected void NotifyValueChanged()
{
if (PropertyChanged != null)
PropertyChanged(this, valueChangedEventArgs);
}
/// <summary>
/// 语言改变通知事件,当程序初始化的时候会绑定到全局的GlobalClass.LanguageChangeEvent事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Language_Event(object sender, EventArgs e)
{
//通知Value值已经改变,需重新获取
NotifyValueChanged();
}
}
}

Resource  [BY Zengg]

//=================================================================================
//
// Copyright (C) 20013-2014
// All rights reserved
//
// description : 本文博客园首发,如果您想转载本博客,请注明出处,感谢支持
// created by Zengg
// http://www.cnblogs.com/01codeworld/
// Email:281365330@qq.com
//==================================================================================
namespace MultilanguageTest
{
public interface IResource
{
string GetString(string name);
CultureInfo CurrentCulture { set; }
}
public class Resource : IResource
{
private ResourceManager stringResource;
//我们这样设置的时候ResourceManager会去查找MultilanguageTest.StringResource.en-us.resx,如果没有会查找MultilanguageTest.StringResource.resx
private CultureInfo culture = new CultureInfo("en-us");
public Resource()
{
//MultilanguageTest.StringResource是根名称,该实例使用指定的System.Reflection.Assmbly查找从指定的跟名称导出的文件中包含的资源
stringResource = new ResourceManager("MultilanguageTest.StringResource", typeof(Resource).Assembly);
}
/// <summary>
/// 通过资源名称获取资源内容
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public string GetString(string name)
{
return stringResource.GetString(name, culture);
}
/// <summary>
/// 改变当前的区域信息,ResourceManager可以通过当前区域信息去查找.resx文件
/// </summary>
public CultureInfo CurrentCulture
{
set
{
culture = value;
}
}
}
}

GlobalClass

//=================================================================================
//
// Copyright (C) 20013-2014
// All rights reserved
//
// description : 本文博客园首发,如果您想转载本博客,请注明出处,感谢支持
// created by Zengg
// http://www.cnblogs.com/01codeworld/
// Email:281365330@qq.com
//==================================================================================
namespace MultilanguageTest
{
/// <summary>
/// 全局类
/// </summary>
public static class GlobalClass
{
static bool? inDesignMode = null;
/// <summary>
/// 判断是设计器还是程序运行
/// </summary>
public static bool InDesignMode
{
get
{
if (inDesignMode == null)
{
#if SILVERLIGHT
inDesignMode = DesignerProperties.IsInDesignTool;
#else
var prop = DesignerProperties.IsInDesignModeProperty;
inDesignMode = (bool)DependencyPropertyDescriptor.FromProperty(prop, typeof(FrameworkElement)).Metadata.DefaultValue; if (!inDesignMode.GetValueOrDefault(false) && Process.GetCurrentProcess().ProcessName.StartsWith("devenv", StringComparison.Ordinal))
inDesignMode = true;
#endif
} return inDesignMode.GetValueOrDefault(false);
}
}
/// <summary>
/// 语言改变通知事件
/// </summary>
public static EventHandler<EventArgs> LanguageChangeEvent;
static Resource StringResource;
static GlobalClass()
{
StringResource = new Resource();
}
/// <summary>
/// 获取资源内容
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string GetString(string key)
{
return StringResource.GetString(key);
}
/// <summary>
/// 改变语言
/// </summary>
/// <param name="language">CultureInfo列表(http://www.csharpwin.com/csharpspace/8948r7277.shtml)</param>
public static void ChangeLanguage(string language)
{
CultureInfo culture = new CultureInfo(language);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture; StringResource.CurrentCulture = culture; if (LanguageChangeEvent != null)
{
LanguageChangeEvent(null, null);
}
}
}
}

MainWindow.xaml

<Window x:Class="MultilanguageTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MultilanguageTest"
Title="MainWindow" Height="" Width="">
<Grid >
<StackPanel Margin="43,54,411,0">
<TextBlock Text="{local:StringResource test1,DefaultValue=测试一}"></TextBlock>
<TextBlock Text="{local:StringResource test2,DefaultValue=测试二}"></TextBlock>
<TextBlock Text="{local:StringResource test3,DefaultValue=测试三}"></TextBlock>
<TextBlock Text="{local:StringResource test4,DefaultValue=测试四}"></TextBlock>
</StackPanel> <Button Content="{local:StringResource btnChina,DefaultValue=中文}" HorizontalAlignment="Left" Margin="389,90,0,0" VerticalAlignment="Top" Width="" Click="Button_Click_1"/>
<Button Content="{local:StringResource btnEnglish,DefaultValue=英文}" HorizontalAlignment="Left" Margin="389,117,0,0" VerticalAlignment="Top" Width="" Click="Button_Click_2"/>
</Grid>
</Window>

  绑定到某个对象的用法就是,如{local:StringResource test1,DefaultValue=测试一},test1是当前资源的资源名称,默认值就是在设计器上显示的内容。

源码地址:http://pan.baidu.com/share/link?shareid=3361221912&uk=554439928

如果您看了本篇博客,觉得对您有所收获,请点击右下角的 [推荐]

如果您想转载本博客,请注明出处

如果您对本文有意见或者建议,欢迎留言

感谢您的阅读,请关注我的后续博客 Zengg

作者:Zengg 出处:http://www.cnblogs.com/01codeworld/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

WPF多语言化的实现的更多相关文章

  1. WPF程序最小化到任务通知栏

    我们通常使用的桌面软件,都可以最小化到任务通知栏,并且可以从任务通知栏再打开当前软件,或者通过软件的快捷方式从任务通知栏呼出. 我们可以通过下面的方式把WPF程序最小化到任务栏.由于WPF并没有实现N ...

  2. 【WinRT】多语言化应用程序名称

    在Windows Phone 8的时候,要对应用程序在列表中显示的名称和锁定到开始屏幕的磁贴的名称进行多语言化是十分困难的,需要使用C++建立一个多语言资源库.但是,在WinRT中,这变得简单多了,无 ...

  3. 项目笔记---WPF多语言方案

    近期由于朋友邀请帮忙给一个开源的游戏“外挂”做一个I18N的解决方案,恰好也是WPF做的,之前有过相关经验,就忙了一个星期终于搞定了,已经提交给作者了,现在这里做一个分享. 这里分享下我个人Fork的 ...

  4. Spring MVC 多语言化的实践和学习

    一.主要参考: SpringMVC简单实现国际化/多语言 - CSDN博客 https://blog.csdn.net/u013360850/article/details/70860144/ 二.总 ...

  5. WPF应用最小化至系统托盘运行

    原文:WPF应用最小化至系统托盘运行 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/lordwish/article/details/5178889 ...

  6. WPF 多语言实现

    很多国际化的程序都提供了多语言的选项,这样方便不同国家的使用者更方便的使用软件.这篇博客中将介绍在WPF中实现多语言的方式. 方式一,使用WPF动态资源的方式实现.先简单介绍下StaticResour ...

  7. winform/WPF 多语言的实现

    WPF实现起来非常现代化,可以参考 https://www.cnblogs.com/yang-fei/p/4854460.html winform主要说一下实现过程和注意点,实现参考AutoUpdat ...

  8. WPF 最大化最小化窗口

    public static void FullOrMin(this Window window)        {            //如果是全屏,则最小化            if (win ...

  9. WPF 多语言 多资源 多皮肤 处理方案

    同时兼容这么多需求的解决方案 我想到的 只有通过 动态切换加载资源字典  前端用绑定的模式 达到托管最大化 多语言举例 我编辑了 两个 语言包 一个中文 一个英文  (语言包这个最好用T4 写个模板, ...

随机推荐

  1. Part 67 to 70 Talking about method parameters in C#

    Part 67 Optional parameters in c# Part 68  Making method parameters optional using method overloadin ...

  2. MySQL之建设工程监管信息系统

    --创建SelfStudy数据库 CREATE DATABASE ConstructionDB ON PRIMARY --创建主数据库文件 ( NAME=' ConstructionDB', --数据 ...

  3. 使用命令修改ip地址

    简述:以serverv 2012 r2为例 常用的几种,当然不全,希望能较快的速率记下一种便可 直接配置 1.      查看网卡的显示名称 2.      配置静态iP地址 3.      查看配置 ...

  4. 复习IOS多线程知识

    线程的注意点 1.不要同时开太多的线程(1~3条线程即可,不要超过5条) 2.线程概念 * 主线程 : UI线程,显示.刷新UI界面,处理UI控件的事件 * 子线程 : 后台线程,异步线程 3.不要把 ...

  5. 两对整数明明完全一样,为何一个输出true,一个输出false?&&神奇代码(StrangeIntegerBehavior.java)输出诡异的结果,原因何在

    下面有一段代码: public class Main {     public static void main(String[] args) {                   Integer ...

  6. lnmp 下安装yaf

    须有配置好的环境 详情见:centos6.5下yum安装lnmp(适合刚入职的新手的方法) http://www.cnblogs.com/qzjpkfj/p/4211126.html 具体安装步骤详情 ...

  7. NSS_08 extjs表单验证

    Extjs做了非常好的表单验证功能, 使用起来非常方便. 系统内置了4种验证功能,分别是alpha, alphanumeric,url, email, 在程序中可以直接使用,(可以结合allowBla ...

  8. PHP 网站保存快捷方式的实现代码

    介绍下使用PHP实现网站快捷方式的保存方法. PHP怎么实现网站保存快捷方式呢?下面是一段PHP代码,下面这段代码,可以PHP实现网站保存快捷方式,以便用户随时浏览.  <?php  /** * ...

  9. crontab的应用

    当我们需要定时执行某个系统内的php脚本程序时,可以这样设置crontab * 19 * * * /usr/local/php/bin/php /var/www/test.php 此处表示调用php( ...

  10. (原创)LINUX_UNIX设计思想-读书笔记

    第一章 一.Unit哲学 1.小即是美 2.让每一个程序只做好一件事情 3.尽快建立原型 4.舍高效率而取可移植性 5.使用纯文本文件来存储数据 6.充分利用软件的杠杆效应 7.使用shell脚本来提 ...