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,如需转载请自行联系原作者

相关文章
|
机器学习/深度学习 计算机视觉 异构计算
RT-DETR改进策略【模型轻量化】| 替换骨干网络 CVPR-2023 FasterNet 高效快速的部分卷积块
RT-DETR改进策略【模型轻量化】| 替换骨干网络 CVPR-2023 FasterNet 高效快速的部分卷积块
483 0
RT-DETR改进策略【模型轻量化】| 替换骨干网络 CVPR-2023 FasterNet 高效快速的部分卷积块
|
7月前
|
数据可视化 C#
使用 OpenTK 构建点云浏览程序
C# 通过USB连接斑马打印机打印ZPL条码
237 0
|
编解码 监控
使用OBS Studio进行多路直播时,有哪些高级设置可以优化同步性?
使用OBS Studio进行多路直播时,有哪些高级设置可以优化同步性?
|
消息中间件 Serverless 数据安全/隐私保护
开发者如何使用云消息队列 RabbitMQ 版
【10月更文挑战第13天】开发者如何使用云消息队列 RabbitMQ 版
637 99
|
运维 监控 持续交付
微服务架构解析:跨越传统架构的技术革命
微服务架构(Microservices Architecture)是一种软件架构风格,它将一个大型的单体应用拆分为多个小而独立的服务,每个服务都可以独立开发、部署和扩展。
3533 37
微服务架构解析:跨越传统架构的技术革命
|
Ubuntu 安全 网络协议
ubuntu22.04防火墙策略
在Ubuntu 22.04中,配置防火墙策略是保障系统安全的关键。UFW提供了简便的界面,适合大多数用户,而iptables则提供了更为强大的功能,适合高级用户和复杂环境。通过合理设计防火墙策略,可以有效防止未经授权的访问,提升系统的安全性和稳定性。无论是通过UFW还是iptables,定期审查和更新防火墙规则都是必不可少的,以应对不断变化的安全威胁。
782 3
|
人工智能 搜索推荐 数据挖掘
让 AI 回答更精准 ◎ 来学学这些Prompt入门小技巧
这篇文章介绍了如何通过有效的提示词来提升向AI提问的质量,使其回答更加精准,并提供了实用的指导原则和案例分析。
让 AI 回答更精准 ◎ 来学学这些Prompt入门小技巧
|
前端开发
[巨详细]使用HBuilder-X新建uniapp项目教程
【6月更文挑战第6天】安装HBuilder-X 详细步骤可看上文》》 启动uniapp项目 先打开HBuilder-X
1094 5
|
前端开发 C#
浅谈WPF之DataGrid动态生成列
在日常开发中,DataGrid作为二维表格,非常适合数据的展示和统计。通常情况下,一般都有固定的格式和确定的数据列展示,但是在某些特殊情况下,也可能会需要用到动态生成列。本文以一些简单的小例子,简述在WPF开发中,如何动态生成DataGrid的行和列,仅供学习分享使用,如有不足之处,还请指正。
741 2
|
算法 C#
winform车牌识别源码(纯算法)
使用C#和Winform开发的纯算法车牌识别系统,无需依赖外部框架。通过去雾、灰度化、均衡化、中值滤波等步骤实现车牌定位和识别。包含详细步骤及源码,适合学习研究。演示视频:[BV1yq4y1a7cb](https://www.bilibili.com/video/BV1yq4y1a7cb/?spm_id_from=333.337.search-card.all.click&vd_source=6d6d1b4c92d36f8d9ca8a23a286bae20)。