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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏圣杰的专栏

Asp.net mvc 知多少(八)

本系列主要翻译自《ASP.NET MVC Interview Questions and Answers 》- By Shailendra Chauhan,想...

2339
来自专栏木宛城主

SharePoint 2013 创建 Site Collection

在之前的文章中,通过SharePoint Central Administration 创建了Web Application。在这篇文章中将继续SharePo...

2156
来自专栏宋凯伦的技术小栈

【Microsoft Azure学习之旅】测试消息队列(Service Bus Queue)是否会丢消息

  组里最近遇到一个问题,微软的Azure Service Bus Queue是否可靠?是否会出现丢失消息的情况?

1231
来自专栏用户2442861的专栏

Java:HttpClient篇,HttpClient4.2在Java中的几则应用:Get、Post参数、Session(会话)保持、Proxy(代理服务器)设置,多线程设置...

新版HttpClient4.2与之前的3.x版本有了很大变化,建议从http://hc.apache.org/处以得到最新的信息。

2431
来自专栏.NET开发者社区

一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](九)

前言 童鞋们,大家好 我是专注.NET开发者社区建设的实践者Rector。 首先,为自己间隔了两个星期五再更新本系列文章找个不充分的理由:Rector最近工作,...

2845
来自专栏菩提树下的杨过

C#代码也VB

习惯于用某一种语言做开发,时间长了以后很多人可能会对其它语言有排斥或抵触,其实... 退一步海阔天空! 比如:经常看到有人问"如何用c# ping 网址?",园...

2276
来自专栏葡萄城控件技术团队

ASP.NET Web API 应用教程(一) ——数据流使用

相信已经有很多文章来介绍ASP.Net Web API 技术,本系列文章主要介绍如何使用数据流,HTTPS,以及可扩展的Web API 方面的技术,系列文章主要...

3728
来自专栏小特工作室

基于Cef内核的多店铺登录器(含源码)

        公司是做电商的,在速卖通平台上开了若干店铺,每天都需要登录店铺打理,如:发货提交、获取运单号等。多个店铺的情况下,同时使用浏览器就会非常繁琐,如...

33710
来自专栏.net core新时代

npoi批量导入实现及相关技巧

  批量导入功能对于大部分后台系统来说都是不可或缺的一部分,常见的场景-基础数据的录入(部门,用户),用批量导入方便快捷。最近项目需要用到批量导入,决定花点时间...

4855
来自专栏技术之路

【权限的思考】(一)使用反射实现动态权限

  每一个业务系统都会根据业务需要配置各种各样的权限,实现方式也是千差万别,各有各的优缺点。今天我们 利用反射来做一个小的权限管理Demo。也可以说是插件化的权...

2179

扫码关注云+社区

领取腾讯云代金券