在使用MVVM模式时, 按照模式的规则是尽量不直接使用事件. 所以对于以前一直使用事件模式的同行来说确实有点头疼. 还好微软给我们提供了几种间接使用事件(命令)的方法, 下面我就来看看这几种方法:

ICommand

ICommand定义了一个接口, 使用它可以轻松的将实现ICommand的接口的命令绑定到包含命令(Command)的控件上(例如Button.Command), 在.net framework库中实现的这个接口的类不是很多, 我所知道的两个: RoutedCommand 和 RoutedUICommand, 而且这两个使用起来比较麻烦, 在这里我就不谈了, 有兴趣的同行可以研究一下. 那么, 除了上述的两个类以外还有自定义类实现ICommand和Prism的DelegateCommand. 我们先看一下自定义的;

1. 自定义命令

MyCommand是实现ICommand接口的一个类. 在Execute方法中我们调用传入的Action(Action包含所要实现的功能的方法), IsEnabledExecute是自定义的一个bool类型, 通过设置该值可以启用(禁用)ICommand所绑定到的控件的启用禁用状态.


定义好MyCommand后我们就可以使用了, 代码如下:

<!--XAML-->

首先定义了MvvmEventViewModel, 在MvvmEventViewModel中实例化了MyCommand, 将Button所在的界面或者用户控件的属性DataContext绑定上MvvmEventViewModel的实例, 最后直接在Button的Command属性上绑定MyCommandInstance;

2.prism命令

prism是微软的一个开源框架, 其为WPF(SL)而生, 自然也少不了MVVM模式的一些辅助类, 其中命令就是典型的辅助类. 在上面我们是自定义命令, 其实在prism框架中已经提供了命令类, 那就是DelegateCommand, 该类还为泛型提供了支持; 不仅如此prism还提供了多个命令的绑定CompositeCommand, 为一个Button命令可以执行多个方法问题提供了廉价的解决方案.

2.1. DelegateCommand 命令

DelegateCommand 命令与我们上面自定义的命令一样, 都是可以绑定到Button的Command属性上, 使用该类少了几行代码, 多了一份省心和安全. 如果让我选择我会选择DelegateCommand类而摒弃自定义类, 因为它可以实现我们需要的功能, 所以就没必要再重造轮子.

<!--XAML-->

2.2.CompositeCommand 命令

CompositeCommand 命令可以理解为一个命令组. 将ICommand注册到CompositeCommand中, 然后绑定在Command上, 就可以让Command触发注册到CompositeCommand的所有命令.

2.2.1.定义一个CompositeCommand命令

2.2.2.使用CompositeCommand命令

Comm.CompositeCommand.RegisterCommand(MyCommandInstance);

Comm.CompositeCommand.RegisterCommand(MyDelegateCommandInstance);

<!--XAML-->

xmlns:comm="clr-namespace:Blogs.WPF"

<Button Width="180"

                Height="23"

                Margin="0,0,7,0"

                HorizontalAlignment="Left"

                Command="{x:Static comm:Comm.CompositeCommand}"

                CommandParameter="DelegateCommand"

                Content="CompositeCommand Button" />

将我们刚才定义的两个命令MyCommandInstance和MyDelegateCommandInstance注册到Comm.CompositeCommand中, 然后在一个Button上绑定 comm:Comm.CompositeCommand 此时我们单击CompositeCommand Button时发现触发了两个命令. 同样的我们也可以使用UnregisterCommand卸载命令.

2.3.将其他事件绑定到ICommand上

在上述的例子中我们只是在Button的Command属性上绑定ICommand, 那么对于一些特殊事件(如Loaded, MouseDown, MouseUp)我们该怎么处理呢? 网上也有一些传统的方法, 将控件直接传送到VM中, 使用+=创建特殊的事件. 其实还有更好的办法, 那就是System.Windows.Interactivity.dll 组件.

在你的项目中引入System.Windows.Interactivity.dll, 然后在页面中添加如下代码: xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

OK, 现在就让我们就来使用这两个组件, 代码简单, 请看:

public DelegateCommand LostFocusCommand { get; private set; }

LostFocusCommand = new DelegateCommand(LostFocusMethod);

private void LostFocusMethod()

{

MessageBox.Show("捕获到了.嘿牟嘿牟.");

}
<TextBlock Background="OrangeRed" Text="左键按下时我能捕获到">

<i:Interaction.Triggers>

<!-- 当单击鼠标左键按下时 -->

<i:EventTrigger EventName="MouseLeftButtonDown">

<i:InvokeCommandAction Command="{Binding LostFocusCommand}" />

</i:EventTrigger>

</i:Interaction.Triggers>

</TextBlock>

注: 名字起的有点不对应. 不想改了, 大家知道就可以.

以上是使用System.Windows.Interactivity.dll组件可以将事件直接绑定到命令上, 但是我觉得这样麻烦, 如果可以直接使用事件岂不是更爽. 呵呵. 能提出问题就能解答问题. 我们再看另一个组件 Microsoft.Expression.Interactions.dll .

同样的, 项目中引用 Microsoft.Expression.Interactions.dll

添加命名空间

xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

<UserControl>

<i:Interaction.Triggers>

<i:EventTrigger EventName="Loaded">

<ei:CallMethodAction MethodName="View_Loaded" TargetObject="{Binding}" />

</i:EventTrigger>

</i:Interaction.Triggers>

</UserControl>

注意: 在多层项目中只要你使用System.Windows.Interactivity.dll, Microsoft.Expression.Interactions.dll 这两个组件,就必须在启动层中引用这两个DLL, 否则报错.

源码地址: 点击下载

http://www.cnblogs.com/ynbt/archive/2013/01/03/2842847.html

MVVM中间接使用事件(命令)的更多相关文章

  1. Visual Studio中“后期生成事件命令行” 中使用XCopy命令

    将程序所依赖的动态库与其他依赖文件做了分类,使用XCopy命令自动生成相应的目录结构. set source="$(TargetDir)" set output="$(S ...

  2. MVVM中轻松实现Command绑定(三)任意事件的Command

    WPF中不是所有的控件都有Command属性的,如果窗体我需要在ViewModel中处理Loaded事件命令,或者其他事件的命令时,很难都过绑定Command完成,必须要注册依赖属性或事件等,太麻烦了 ...

  3. WPF使用MVVM(三)-事件转命令

    WPF使用MVVM(三)-事件转命令 上一节介绍了WPF中的命令,可是仅仅介绍的是WPF框架给我们提供的点击命令,也就是用Command属性来绑定一个命令,用来响应按钮的点击行为!显然这是不够的,界面 ...

  4. 整理:WPF中应用附加事件制作可以绑定命令的其他事件

    原文:整理:WPF中应用附加事件制作可以绑定命令的其他事件 目的:应用附加事件的方式定义可以绑定的事件,如MouseLeftButton.MouseDouble等等 一.定义属于Control的附加事 ...

  5. 使用VS的生成事件命令行指令将生成的exe,dll文件复制到指定文件夹中

    VS预生成事件命令行 和 生成后事件命令行 宏说明 $(ConfigurationName)            当前项目配置的名称(例如,“Debug|Any CPU”). $(OutDir)   ...

  6. Messenger和MVVM中的View Services

    在前面的文章IoC容器和MVVM中, 介绍了IoC容器如何在大量用户类中帮助创建和分配用户类的实例.本文将介绍IoC容器如何帮助应用程序解耦,比如那些根据MVVM模式开发的应用.此模 式广泛应用在基于 ...

  7. 从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator-更新至Prism7.1

    原文:从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator-更新至Prism7.1 事件聚合器EventAggregator [7.1updated]除了app部分,没 ...

  8. 从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator?

    原文:从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator? 从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WP ...

  9. 五、从GitHub浏览Prism示例代码的方式入门WPF下的Prism之MVVM中的EventAggregator

    这一篇我们主要再看完示例12.13后,写了个例子,用于再Modules下执行ApplicationCommands,使用IActiveAware执行当前View的Commands,或者Applicat ...

随机推荐

  1. 新增分区格式化时提示设备文件不存在:--- No such file or directory的处理方法

    [原文链接]:http://blog.itpub.net/28874898/viewspace-774249/ 在系统中的空余空间添加新的分区:   fdisk   /dev/sda (第一块硬盘上) ...

  2. MSSQL日期分组排序

    等于今天日期的排上面,大于今天的排中间,小于今天的排下面,带分页.

  3. oracle修改某个表的字段顺序

    有时候会发现某个表的列顺序不理想,想修改 -1查询表, select * from AIRWAY_TYPE t --2 查询用户和表名,找到obj#,select object_id from all ...

  4. Ubuntu 部署Python开发环境

    一.开发环境包安装 sudo apt-get install git-core sudo apt-get install libxml2-dev sudo apt-get install libxsl ...

  5. HTML5 Geolocation学习

    GeolocationAPI学习,我写的挺枯燥的,直接跳到最后看示例. 5.1 位置信息 HTML5 Geolocation API的使用方法相当简单.请求一个位置信息,如果用户同意,浏览器就会返回位 ...

  6. Spring资源

    资源 官网:http://spring.io 文档:https://docs.spring.io/spring/docs/current/spring-framework-reference/.htt ...

  7. Angular7和leaflet一起使用时的作用域不一致

    Angular7和leaflet一起使用时的作用域不一致问题,使用(e) =>可以完美解决. 使用原始的JavaScript: map.on("click", functio ...

  8. pgadmin4 csrf错误导致docker-compose postgres服务下线

    docker-compse up 启动的前台服务, 过一会就自动停止 检查半天,发现是pgadmin4没安装正确不断报400 和 csrf error 然后pgadmin4为啥报这个, 因为pytho ...

  9. 成功解决internal/modules/cjs/loader.js:596 throw err; ^ Error: Cannot find module 'minimatch'

    成功解决internal/modules/cjs/loader.js:596 throw err; ^ Error: Cannot find module 'minimatch' 解决办法 npm i ...

  10. Linux命令-文件管理(四)

    Linux命令-文件管理 Linux slocate命令 Linux slocate命令查找文件或目录. slocate本身具有一个数据库,里面存放了系统中文件与目录的相关信息. 语法 slocate ...