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 98 Anonymous methods in c#

    What is an anonymous method? Anonymous method is a method without a name. Introduced in C# 2.0,they ...

  2. jQuery中append、insertBefore、after与insertAfter方法注意事项

    这里列的是针对初学jQuery者来说容易搞不懂的部分,我在这里把这些方法列了个清单,希望大家能看的懂.如下: 方法 源包装集/字串 目标包装集体 特性描述 A.append(B) B A 若目标包装集 ...

  3. 【学习笔记】【C语言】进制

    1. 什么是进制 是一种计数的方式,数值的表示形式 2. 二进制 1> 特点:只有0和1,逢2进1 2> 书写格式:0b或者0b开头 3> 使用场合:二进制指令\二进制文件,变量在内 ...

  4. UI3_ViewController初步

    // // AppDelegate.m // UI3_ViewController初步 // // Created by zhangxueming on 15/6/30. // Copyright ( ...

  5. AMQ学习笔记 - 20. 使用Apache ActiveMQBrowser监控ActiveMQ

    概述 Apache ActiveMQBrowser可以用于查看AMQ中的消息.这里对其使用方法进行简单介绍. 使用介绍 1.下载并解压缩 下载地址:Apache ActiveMQBrowser,当前最 ...

  6. html5 拖曳功能的实现[转]

    HTML5中实现拖放操作,至少经过如下步骤1)设置被拖放对象元素的draggable属性设置为true2)编写与拖放有关的事件处理代码 事件 产生事件的元素 描述 dragstart 被拖拽物体 开始 ...

  7. 为apache与mysql创建快捷方式

    为apache与mysql创建快捷方式 1)为apache创建快捷方式(软链接) 以后我们就可以在终端的任一位置,使用apachectl start|stop|restart   2)为mysql创建 ...

  8. http请求访问过程

    流程图(理解): 域名的作用: 对外,供访问 对内,提供域名与目录的对应关系 步骤说明: http://www.163.com/index.html 第1步:在本机的hosts文件中查找域名与IP的对 ...

  9. windows phone 自定义铃声

    屌丝的电话是一个月都响不了几次的,无聊还是下了一个XX铃声,自娱自乐一下,google了一下实现原理,,,,,,真相啊!!!就是用了一个Task(SaveRingtoneTask),以前看的资料都没有 ...

  10. 《Apache之虚拟主机的配置》——RHEL6.3

    1.安装httpd软件包: Yum install httpd 2.启动apache服务: [root@redhat Desktop]# /etc/init.d/httpd start Startin ...