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

简介:

Caliburn.Micro学习笔记目录

说一下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

 本文转自lpxxn博客园博客,原文链接:http://www.cnblogs.com/li-peng/p/3433974.html,如需转载请自行联系原作者

相关文章
|
自然语言处理 安全 Java
Google Tink多语言跨平台加密演示
Google Tink多语言跨平台加密演示
415 0
|
4月前
|
存储 自然语言处理 监控
【Unity 实用工具篇】| 游戏多语言解决方案,官方插件Localization 实现本地化及多种语言切换
Unity的多语言本地化是一个很实用的功能,它可以帮助游戏支持多种语言,让不同语言的玩家都能够更好地体验游戏。 而实现本地化的方案也有很多种,各个方案之间也各有优劣,后面也会对多个方案进行介绍学习。 本文就来介绍一个专门作用于多语言本地化的Unity官方插件:Localization 。 这个插件方便进行游戏的多语言本地化,让游戏支持多种语言,下面就来看看该插件的使用方法吧!
|
8月前
|
开发框架
HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 四)
被@Observed装饰的类,可以被观察到属性的变化;子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed装饰的项,或者是class object中是属性,这个属性同样也需要被@Observed装饰。单独使用@Observed是没有任何作用的,需要搭配@ObjectLink或者@Prop使用。
|
5月前
|
存储 安全 数据安全/隐私保护
HarmonyOS 高级特性
本章将探讨 HarmonyOS 的高级特性,包括分布式能力、安全机制和性能优化。这些特性可以帮助你构建更强大、更安全、更高效的应用。
51 0
|
8月前
|
存储 开发框架 JavaScript
HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 五)
LocalStorage是ArkTS为构建页面级别状态变量提供存储的内存内“数据库”。应用程序可以创建多个LocalStorage实例,LocalStorage实例可以在页面内共享,也可以通过GetShared接口,获取在UIAbility里创建的GetShared,实现跨页面、UIAbility内共享。组件树的根节点,即被@Entry装饰的@Component,可以被分配一个LocalStorage实例,此组件的所有子组件实例将自动获得对该LocalStorage实例的访问权限;
|
8月前
|
开发框架
HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 二)
@Prop装饰器:父子单向同步 @Prop装饰的变量可以和父组件建立单向的同步关系。@Prop装饰的变量是可变的,但是变化不会同步回其父组件。
|
自然语言处理 开发者
多语言| 学习笔记
快速学习多语言。
68 0
|
自然语言处理 架构师 开发者
多语言|学习笔记
快速学习多语言。
71 0
多语言|学习笔记
|
编译器 C语言
QT应用编程: QtCreate编译部署开源音视频框架模块QtAV
QT应用编程: QtCreate编译部署开源音视频框架模块QtAV
167 0
QT应用编程: QtCreate编译部署开源音视频框架模块QtAV