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. 常见的Activity Action Intent常量

    Intent的中文意思是“意图,目的”的意思,可以理解为不同组件之间通信的“媒介”或者“信使”. 目标组件一般要通过Intent来声明自己的条件,一般通过组件中的<intent-filter&g ...

  2. 让项目管理理论“落地”——读《IT项目经理成长手记》有感

    最近利用业余时间阅读了一本好书--<IT项目经理成长手记>(潘东.韩秋泉著).本书的两位作者是神州数码(中国本土最大的整合IT服务提供商)的高管,在书中他们介绍了神州数码在IT项目管理领域 ...

  3. 50个常用的笔试、面试sql语句

    50个常用的笔试.面试sql语句 2009-12-17 15:05   Student(S#,Sname,Sage,Ssex) 学生表Course(C#,Cname,T#) 课程表SC(S#,C#,s ...

  4. jQuery中的DOM操作<思维导图>

    DOM是Document Object Model的缩写,意思是文档对象模型.DOM是一种与浏览器.平台.语言无关的接口.使用该接口可以轻松地访问页面中所有的标准组件.简单来说,DOM解决了Netsc ...

  5. iOS 数据模型 的 一般设计

  6. js 正则表达式 手机号

    js--手机号验证 //注册验证 function RegsiterBtn() { var regphone = $("#regphone").val(); var regreal ...

  7. javascript之基本包装类型(Boolean,Number,String)基础篇

    前几天整理了javascript中Array方面的知识,但是String中的一些方法多多少少和Array里的方法有些类似容易混淆,就顺便连同String所在的包装类一起整理一下,希望可以帮助到初学者, ...

  8. mybatis 聚合查询

    <resultMap id="ExtResultMap" type="com.demo.partner.po.PartnerPO"> <id ...

  9. Android四大组件之一:Service(服务)

    Service跟Activity也是出于统一级别的组件,且与Activity的最大区别之一主要是没有人机界面,主要是运行在程序的后台(我是这么理解的),帮助文档上说的是运行于进程的主线程中,但是服务并 ...

  10. 链接与ELF文件格式的复习

    在这里复习一下链接的知识: 什么是链接(linking):把源代码形成的模块独立编译后组装成一个整体的的过程叫做链接. 链接主要过程包括:地址和空间分配(address and storage all ...