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
作者:李鵬
出處:http://www.cnblogs.com/li-peng/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。