Caliburn.Micro的Action介绍

本文通过示例代码详细介绍了Caliburn.Micro框架中Action的使用方法,包括事件响应、参数传递及MEF集成等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

就我个人的理解,Caliburn.Micro的Action其实为我们实现了事件的响应以及事件参数的传递。废话不多说,直接看代码:

1.新建一个工程,取名为:CaliburnMicroAction。

2.新建一个ViewModel,取名为MainViewModel,其代码如下:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class MainViewModel:PropertyChangedBase,IShell {  
  2.   
  3.     private string mytxt;  
  4.     public string Mytxt {  
  5.         get {   
  6.             return mytxt;  
  7.         }  
  8.         set {   
  9.             mytxt = value;  
  10.             NotifyOfPropertyChange(() => Mytxt);  
  11.             NotifyOfPropertyChange(() => CanMyClick);  
  12.         }  
  13.     }  
  14.   
  15.     public bool CanMyClick {  
  16.         get {   
  17.             return !string.IsNullOrEmpty(mytxt);   
  18.         }  
  19.     }  
  20.   
  21.     public void MyClick(object ob, string str2) {   
  22.         MessageBox.Show(ob.ToString() +" " + str2);  
  23.     }  
  24. }  
说明:IShell接口需要定义,此处的IShell接口的实现时候为了配合MEF的使用

3.根据ViewModel,新建View,代码如下:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <StackPanel>  
  2.        <TextBox x:Name="Mytxt" />  
  3.   
  4.        <Button Height="30" Margin="0,3" Content="Click Me">  
  5.            <i:Interaction.Triggers>  
  6.                <i:EventTrigger EventName="Click">  
  7.                    <cal:ActionMessage MethodName="MyClick">  
  8.                        <cal:Parameter Value="{Binding ElementName=Mytxt,Path=Text}"/>  
  9.                        <cal:Parameter Value="aaabbbccc"/>  
  10.                    </cal:ActionMessage>  
  11.                </i:EventTrigger>  
  12.            </i:Interaction.Triggers>  
  13.        </Button>  
  14.        <Button Height="30" Margin="0,3" Content="Click Me2" cal:Message.Attach="[Event Click]=[Action MyClick($source,'xiao')]"></Button>  
  15. </StackPanel>  
其中

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <i:Interaction.Triggers>  
  2.        <i:EventTrigger EventName="Click">  
  3.               <cal:ActionMessage MethodName="MyClick">  
  4.                         <cal:Parameter Value="{Binding ElementName=Mytxt,Path=Text}"/>  
  5.                         <cal:Parameter Value="aaabbbccc"/>  
  6.               </cal:ActionMessage>  
  7.        </i:EventTrigger>  
  8. </i:Interaction.Triggers>  

是控件的Click事件绑定的语法(长语法),其中EventTrigger可以指定哪个事件需要监听监听,通过Caliburn Micro的ActionMessage我们可以指定哪些方法应该调用。 使用这种方法可以使用相同的控制包含任意数量的事件触发监听其他事件。<cal:Parameter />表明此函数传递的参数是String类型的名称为Mytxt的元素的Text属性和字符串aaabbbccc。

这里ActionMessage处理的事情有二:

通过名字匹配自动把ShellViewModel设置为ShellView的DataContext。
通过反射用名字取到对应的方法,Invoke该方法。
这个思路是很清晰的,第一步的匹配是CM中的一个特色Convention,自动匹配XXViewModel和XXView。第二步会在前面查到的XXViewModel中查询名字为Show的MethodInfo,然后反射调用。

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. cal:Message.Attach="[Event Click]=[Action MyClick($source,'xiao')]"  
是控件的Click事件绑定的另外一种语法(短语法),事件的参数写在方法名称的方括号后。如果有多个事件需要响应,按如下方式书写即可:<Button cm:Message.Attach="[Event MouseEnter] = [Action Show('Enter')]; [Event MouseLeave] = [Action Show('Leave')]" />

这个Action,简单来说就是在事件A发生时执行对象B的C方法,
ActionMessage是继承自TriggerAction<FrameworkElement>的,TriggerAction来自于Blend的Interactivity,在事件A被执行时会调用到ActionMessage的Invoke方法。关于Blend的TriggerBase不是本文讨论的重点,只是说明事件A这一步由Blend保证完成。
在创建ActionMessage的时候设置了属性MethodName,这个MethodName指明了C方法,那么整个ActionMessage的关键就是如何找到对应的B对象。

4.定义IShell接口,代码如下:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public interface IShell {  
  2. }  
此接口没有实质性用途,只是为MEF的使用提供基础。

5.实现BootStrapper,代码如下:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class AppBootStrapper : BootstrapperBase {  
  2.   
  3.     public AppBootStrapper() {  
  4.         Initialize();  
  5.     }  
  6.   
  7.     private CompositionContainer _container;  
  8.     protected override void Configure() {  
  9.         AggregateCatalog _catalog = new AggregateCatalog(  
  10.             AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());  
  11.         _container = new CompositionContainer(_catalog);  
  12.   
  13.         CompositionBatch _batch = new CompositionBatch();  
  14.         _batch.AddExportedValue<IWindowManager>(new WindowManager());  
  15.         _batch.AddExportedValue<IEventAggregator>(new EventAggregator());  
  16.   
  17.         _batch.AddExportedValue(_container);  
  18.         _container.Compose(_batch);  
  19.         Coroutine.Completed += (s, e) => {  
  20.             if (e.Error != null) {  
  21.                 MessageBox.Show(e.Error.Message);  
  22.             }  
  23.         };  
  24.         //注意这个$mysender 都是小写的在view层写的时候可以不区分大小写  
  25.         MessageBinder.SpecialValues.Add("$mysender", ctx => {  
  26.             var _ui = ctx.Source as UIElement;  
  27.             return _ui;  
  28.         });  
  29.   
  30.     }  
  31.   
  32.     protected override object GetInstance(Type service, string key) {  
  33.         string _contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(service) : key;  
  34.         var _exports = _container.GetExportedValues<object>(_contract);  
  35.         if (_exports.Any()) {  
  36.             return _exports.First();  
  37.         }  
  38.         throw new Exception(string.Format("找不到{0}实例!", _contract));  
  39.     }  
  40.   
  41.     protected override IEnumerable<object> GetAllInstances(Type service) {  
  42.         return _container.GetExportedValues<object>(AttributedModelServices.GetContractName(service));  
  43.     }  
  44.   
  45.     protected override void BuildUp(object instance) {  
  46.         _container.SatisfyImportsOnce(instance);  
  47.     }  
  48.     protected override IEnumerable<Assembly> SelectAssemblies() {  
  49.         return new[] {  
  50.             Assembly.GetExecutingAssembly()  
  51.         };  
  52.     }  
  53.     protected override void OnStartup(object sender, StartupEventArgs e) {  
  54.         DisplayRootViewFor<IShell>();  
  55.     }  
  56. }  
上面的代码简单实现了MEF的框架和原理,详细的MEF的知识,各位可以自己去理解!

6.将ViewModel输出成IShell类型,遵守MEF的契约,实现方式如下:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. [Export(typeof(IShell))]  

7.在App.xmal中添加BootStrapper,代码如下:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <Application.Resources>  
  2.         <ResourceDictionary>  
  3.             <ResourceDictionary.MergedDictionaries>  
  4.                 <ResourceDictionary>  
  5.                     <local:AppBootStrapper x:Key="appboot"/>  
  6.                 </ResourceDictionary>  
  7.             </ResourceDictionary.MergedDictionaries>  
  8.         </ResourceDictionary>  
  9. </Application.Resources>  


8.Enjoy it!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值