Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能

Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能

说一下IHandle<T>实现多语言功能

因为Caliburn.Micro是基于MvvM的UI与codebehind分离,

binding可以是双向的所以我们想动态的实现多语言切换很是方便今天我做一个小demo给大家提供一个思路

先看一下效果

点击英文  变成英文状态点chinese就会变成中文

                        

源码的下载地址在文章的最下边

多语言用的是资源文件建一个MyLanguage的资源文件再添加一个MyLanguage.en-US的资源文件如果你还想要

其它的语言可自己添加。两个资源文件里写上你要的文本如下图这样,它们的名称是一样的只是值一个是中文一个是英文

下面我们就要开始用Caliburn.Micro的IHandle<T>去实现多语言了

先写一个资源的接口

 public interface IResource
    {
        string GetString(string name);
        CultureInfo CurrentCulture { set; }
    }

    public interface IResourceTask
    {
        void ChangeLanguage(string language);
        string GetString(string name);
        event EventHandler LanguageChanged;
    }    

IResource接口是资源要实现的,GetString(stirng name)方法是得到根据名字得到资源里的值
CurrentCulture是中英文语言转换的

ResourceTask接口是一个管理接口它管理资源的我们通过它去实现

语言转换时把发送广播把页面上的所有文字转换成想要的语言。

再写一个简单的信息接口,也就是我们发送广播时的数据格式

public interface IMessage
    {

    }
    public class LanguageChangedMessage : IMessage
    {

    }

LanguageChangedMessage就是我们要发送广播的数据格式
下面就来实现一下IResourceTask接口

    public class ResourceTask : IResourceTask
    {
        public ResourceTask()
        {
            System.Data.DataTable _dt = new System.Data.DataTable();

        }
        [ImportMany]
        public IResource[] Resources { get; set; }

        public void ChangeLanguage(string language)
        {
            CultureInfo culture = new CultureInfo(language);
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;

            Resources.Apply(item => item.CurrentCulture = culture);

            IEventAggregator eventAggregator = IoC.Get<IEventAggregator>();
            eventAggregator.Publish(new LanguageChangedMessage());

            if (LanguageChanged != null)
            {
                LanguageChanged(this, null);
            }
        }
        public event EventHandler LanguageChanged;

        public string GetString(string name)
        {
            string str = null;

            foreach (var resource in Resources)
            {
                str = resource.GetString(name);
                if (str != null)
                {
                    break;
                }
            }
            return str;
        }
    }

通过Resources得到所有export IResource的类

ChangeLanguage(string language)方法里的

Resources.Apply(item => item.CurrentCulture = culture);是把所有实现IResult类的CurrentCulture修改成我们要换成的语言格式

eventAggregator.Publish(new LanguageChangedMessage()); 就是去发送广播,把页面上所有的的文字切换

EventHandler LanguageChanged;事件是如果我们还想切换完语言后做一些事件就可以写在这个事件里

再写一个实现 IResult的类

    [Export(typeof(IResource))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class MyResource :  IResource
    {

        private ResourceManager stringResource;
        private CultureInfo culture = new CultureInfo("zh-cn");
        public CultureInfo CurrentCulture
        {
            get
            {
                return culture;
            }
            set
            {
                culture = value;
            }
        }

        public MyResource()
        {
            stringResource = new ResourceManager("WPFMultLanguage.Resource.MyLanguage", typeof(MyResource).Assembly);
        }

        public string GetString(string name)
        {
            return stringResource.GetString(name, culture);
        }

    }

ResourceManager 可以对我们前边写的两种语言的资源文件的读写

在类初始化的时候我们给出资源文件的路径

在GetString(string name)里我们就可以通过ResourceManager根据当前的culture去读取资源文件里的字符了

接下来的问题就是我们怎么去通过接收广播把页面上把文字切换

我们写一个 XAML 标记扩展类

 public class MyResourceExtension : MarkupExtension, INotifyPropertyChanged, IHandle<LanguageChangedMessage>
    {
        public string Key
        {
            get;
            set;
        }
        public string Value
        {
            get
            {
                if (Key == null)
                {
                    return null;
                }
                IResourceTask result = IoC.Get<IResourceTask>();
                string s = result.GetString(Key);
                return s;
            }
        }
        public MyResourceExtension()
        {

            if (!Execute.InDesignMode)
            {
                IoC.Get<IEventAggregator>().Subscribe(this);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void PropertyChanted()
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Value"));
            }
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
            Binding binding = new Binding("Value") { Source = this, Mode = BindingMode.OneWay };
            return binding.ProvideValue(serviceProvider) as BindingExpression;
        }

        public void Handle(LanguageChangedMessage message)
        {
            PropertyChanted();
        }
    }

这个类我们要实现MarkupExtension基类这样我们才能把我们的类可以在xmal里标识出来

我们要重写一下ProvideValue(IServiceProvider serviceProvider)方法这里我们是要把Value双向绑定到页面上

这个类实现了还INotifyPropertyChanged和IHandle<LanguageChangedMessage>接口

这两个类能干什么我想你们应该都知道吧一个是用来binging的一个是用来接收消息的

Key就是我资源文件里的名称项

value是资源文件里的值项看一下它的get也可以看来出是通过IResourceTask的getstring把值取出来

接口信息的方法Handle(LanguageChangedMessage message)

只要有消息过来我们就PropertyChanged  Value值这样就可以 把字符切换了,

我们再看一下前台页面是怎么处理的

<Window x:Class="WPFMultLanguage.Views.MyView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFMultLanguage.Command"
        xmlns:cal="http://www.caliburnproject.org"
        cal:Message.Attach="[Event Loaded]=[Action LoadEvent($source)]"
        Title="MyView" Height="300" Width="300">
    <StackPanel>
        <Menu>
            <MenuItem Header="{local:MyResource Key=英文}" cal:Message.Attach="[Event Click]=[Action ChanguageLanguage(‘en‘)]"></MenuItem>
            <MenuItem Header="{local:MyResource Key=中文}"  cal:Message.Attach="[Event Click]=[Action ChanguageLanguage(‘zh‘)]"></MenuItem>
        </Menu>
        <TextBlock Text="{local:MyResource Key=语言}"/>
        <Button Content="{local:MyResource Key=你好}"/>
        <TextBox x:Name="tb_Show" Text="{local:MyResource Key=文本}"></TextBox>
        <TextBox x:Name="tb_Load" Text="{local:MyResource Key=文本2}"></TextBox>
    </StackPanel>
</Window>

xmlns:local="clr-namespace:WPFMultLanguage.Command"

这样是把我们上边写的的xaml扩展类放到页面上 Header="{local:MyResource Key=英文}"

这样每一个控件都会初始化一个MyResourceExtension类都会去订阅IHandle<LanguageChangedMessage>广播

再看一下viewModel

namespace WPFMultLanguage.ViewModels
{
    [Export(typeof(IShell))]
    public class MyViewModel :Screen
    {
        public MyViewModel()
        {
        }

        public void LoadEvent(object obj)
        {
             //var res = IoC.Get<IResourceTask>();
             //((MyView)GetView()).tb_Load.Text = res.GetString("文本2");
        }

        public void ChanguageLanguage(string lan)
        {
            var res = IoC.Get<IResourceTask>();

            switch (lan)
            {
                case "zh":
                    res.ChangeLanguage("zh-CN");
                    break;
                case "en":
                    res.ChangeLanguage("en-US");
                    break;
            }
        }
    }
}

源码:WPFMultLanguageDemo.rar

时间: 2024-12-26 19:26:16

Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能的相关文章

Caliburn.Micro学习笔记目录——li-peng

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则 Caliburn.Micro学习笔记(二)----Actions Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle<T> Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能 Caliburn.Micro学习笔记(五)----协同IResult

Caliburn.Micro学习笔记目录

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则 Caliburn.Micro学习笔记(二)----Actions Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle<T> Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能 Caliburn.Micro学习笔记(五)----协同IResult

Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle&lt;T&gt;

Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle<T> 今天 说一下Caliburn.Micro的IEventAggregator和IHandle<T>分成两篇去讲这一篇写一个简单的例子 看一它的的实现和源码 下一篇用它们做一个多语言的demo 这两个是事件的订阅和广播,很强大,但用的时候要小心发生不必要的冲突. 先看一下它的实现思想 在Caliburn.Micro里EventAggregator要以单例的形式出现这样可以

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则 用了几天时间看了一下开源框架Caliburn.Micro 这是他源码的地址http://caliburnmicro.codeplex.com/ 文档也写的很详细,自己在看它的文档和代码时写了一些demo和笔记,还有它实现的原理记录一下 学习Caliburn.Micro要有MEF和MVVM的基础 先说一下他的命名规则和引导类 以后我会把Caliburn.Micro的 Actions IResult,IHandle ICondu

Caliburn.Micro学习笔记(二)----Actions

Caliburn.Micro学习笔记(二)----Actions 上一篇已经简单说了一下引导类和简单的控件绑定 我的上一个例子里的button自动匹配到ViewModel事件你一定感觉很好玩吧 今天说一下它的Actions,看一下Caliburn.Micro给我们提供了多强大的支持 我们还是从做例子开始 demo的源码下载在文章的最后 例子1.无参数方法调用 点击button把textBox输入的文本弹出来 如果textbox里没有文本button不可点,看一下效果图 看一下前台代码 <Stac

Caliburn.Micro学习笔记(五)----协同IResult

Caliburn.Micro学习笔记(五)----协同IResult 今天说一下协同IResult 看一下IResult接口 /// <summary> /// Allows custom code to execute after the return of a action. /// </summary> public interface IResult { /// <summary> /// Executes the result using the specif

代码管理工具 --- git的学习笔记四《重新整理git(1)》

1.创建版本库 mkdir  创建目录 cd  地址,到该地址下 pwd 显示当前目录 1.创建目录 $ mkdir startGit $ cd startGit $ pwd 显示当前目录 或者cd到桌面,然后再创建目录 2.初始化版本库 $ git init 初始化仓库 提示信息:Initialized empty Git repository in /Users/xingzai/Desktop/startGit/.git/ 建立一个空的git仓库在/Users/xingzai/Desktop

Linux学习笔记四:Linux的文件搜索命令

1.文件搜索命令  which 语法:which [命令名称] 范例:$which ls  列出ls命令所在目录 [[email protected] ~]$ which ls alias ls='ls --color=auto' /bin/ls 另外一个命令:whereis [名称名称],也可以列出命令所在目录. [[email protected] ~]$ whereis ls ls: /bin/ls /usr/share/man/man1/ls.1.gz /usr/share/man/ma

小猪的数据结构学习笔记(四)

小猪的数据结构学习笔记(四) 线性表之静态链表 --转载请注明出处:coder-pig 本章引言: 在二,三中中我们分别学习了顺序表中的线性表与单链表,线性表有点类似于 我们前面所学的数组,而单链表使用的最多的是指针,这里问个简单的问题, 如果是在以前没有指针的话,前辈先人们怎么实现单链表呢?大家思考下! 没有指针,那么用什么来代替呢?前辈先人们非常机智,想出了使用下标+游标的方式 来实现单链表的效果!也就是今天要讲的--静态链表! 当然你也可以直接跳过本章,因为有了单链表就没有必要用静态链表了