管窥MVVMLight Command参数绑定和事件传递
前言
由于在实际项目中,业务功能的增加导致软件开发规模在逐渐变大,所以我准备找个Silverlight框架来组织当前项目中的文件,以期能够让后续的业务功能增添和维护更加容易一些。无意中,我在这篇文章中看到了当前Silverlight下所有的框架的评测:Discover and compare existing MVVM frameworks !,当我看到MvvmLight toolkit在各方面都比较完备的时候,于是决定选择这个框架:
在Codeplex网站上,下载了MVVM Light Toolkit V4 RTM这个版本,因为我用的是vs2010,所以我下载了支持当前机器IDE的版本。
新建项目,选择MvvmLight(SL4),之后我们就可以看到项目结构了:
其中:
Design文件夹中的文件主要提供设计时运行支持
Model文件夹则放置了富实体模型
Skins文件夹则放置了样式文件定义
ViewModel文件夹则放置了ViewModel对象,其实MainViewModel和MainPage是一对一的(ViewMoel-View)关系.二者的映射通过ViewModelLocator进行。
MainPage.xaml就是我们的视图页面
下面我们就以例子来演示MvvmLight Toolkit中是如何实现MVVM模式,如何绑定命令,如何进行事件消息传递的。
首先,在这个框架中,MVVM模式的入口点为ViewModelLocator类,在这个类中,可以定义多个ViewModel属性,并且每个属性都可以通过ServiceLocator.Current.GetInstance方法进行映射,以便于暴露给前台绑定。同时,在新增一个ViewModel类的时候,一定要在其提供的SimpleIoc对象容器中进行注册,以便于能够通过IOC的方式获取其实例。
做完映射后,就是我们的ViewModel对象了。它需要继承自ViewModelBase类,这个类封装了ICommand,INotifypropertyChanged等接口,使用起来很方便。比如可以用RaisePropertyChanged直接来抛出变更通知。
之后就是View了,在View中,我们需要先对DataContext进行绑定:
DataContext="{Binding Main, Source={StaticResource Locator}}"
然后就可以随心所欲的操作了。
然后,我们来讲解下绑定命令。
由于命令绑定是应用程序中必不可少的环节,所以这里我以 绑定无参事件,绑定一个参数事件,绑定多个参数事件来说明。
绑定无参事件:
#region Command without parameters
private RelayCommand showText;
public RelayCommand ShowText
{
get
{
if (showText == null)
showText = new RelayCommand(ShowTextFunc);
return showText;
}
}
public RelayCommand PassEvent { get; set; } private void ShowTextFunc()
{
MessageBox.Show("I am RealyCommand!");
}
#endregion
上面代码就是绑定无参事件,在View上可以通过如下方式绑定:
<Button Content="绑定无参事件"
Command="{Binding ShowText}"
Height="23"
HorizontalAlignment="Left"
Margin="32,62,0,0"
Name="button1"
VerticalAlignment="Top"
Width="141" />
绑定一个参数事件:
#region Command with a parameter
private RelayCommand<int> showValue;
public RelayCommand<int> ShowValue
{
get
{
if (showValue == null)
showValue = new RelayCommand<int>(x=>ShowValueFunc(x));
return showValue;
}
} private int ShowValueFunc(int a)
{
int c = a + 10;
MessageBox.Show(c.ToString());
return c;
}
#endregion
上面的代码部分就是绑定一个参数的事件定义,我们来驱动view层:
<Button Content="绑定一个参数事件"
Command="{Binding ShowValue}"
CommandParameter="{Binding ElementName=textBox1,Path=Text,Converter={StaticResource IntConverter}}"
Height="23"
HorizontalAlignment="Left"
Margin="32,103,0,0"
Name="button2"
VerticalAlignment="Top"
Width="141" />
需要说明的是,上面代码示例中,CommandParameter的值来自于textBox1的Text属性中。这个值加上10以后返回。
如果遇到用户输入不是数字的情况,则通过IntConverter方法将用户输入格式化,然后返回:
public class IntConverter:IValueConverter
{ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int result;
if(Int32.TryParse(value.ToString(),out result))
{
return result;
}
return "0";
} public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
绑定多个参数事件:
由于RelayCommand默认最多允许一个参数传递,所以这里如果想传递多个数据对象,只能够去构建自己的DTO了。
在Model文件夹新建一个BookItem类:
public class BookItem
{
public string BName { get; set; }
public string BAuthor { get; set; }
}
然后在ViewModel中进行如下控制:
#region Command with multiple parameters
private RelayCommand<BookItem> showBooks;
public RelayCommand<BookItem> ShowBooks
{
get
{
if (showBooks == null)
showBooks = new RelayCommand<BookItem>(x=>ShowBooksFunc(x));
return showBooks;
}
} private void ShowBooksFunc(BookItem bookItem)
{
MessageBox.Show(bookItem.BName+"|"+bookItem.BAuthor);
}
#endregion
驱动View层:
<Button Command="{Binding ShowBooks}"
Content="绑定多个参数事件"
Height="23"
HorizontalAlignment="Left"
Margin="32,141,0,0"
Name="button3"
VerticalAlignment="Top"
Width="141" >
<Button.CommandParameter>
<model:BookItem BName="testName" BAuthor="TestAuthor" ></model:BookItem>
</Button.CommandParameter>
</Button>
运行起来得时候,我们发现BookItem参数已经被自动赋值了。
ViewModel之间事件传递
最后需要讲解的是如何在ViewModel之间进行事件传递。由于在MVVMLight Toolkit中已经集成了Messenger对象,所以我们可以利用其很方便的进行事件传递,下面新建一个ChildWindow1.xaml子窗体,然后在ViewModelLocator中添加如下代码:
public ChildViewModel Child
{
get
{
return ServiceLocator.Current.GetInstance<ChildViewModel>();
}
}
SimpleIoc.Default.Register<ChildViewModel>();
然后在ViewModel文件夹中新建一个ChildViewModel类,在其中添加如下代码:
public class ChildViewModel:ViewModelBase
{
public ChildViewModel()
{
Messenger.Default.Register<BookItem>(this, message =>
{
MyText = message.BName + "|" + message.BAuthor;
});
}
public string MyText { get; set; }
}
由于我们传递的对象是从 MainViewModel到ChildViewModel,所以我们在MainViewModel中添加如下发送代码:
#region Messenger communication cross page
private RelayCommand showChildWindow;
public RelayCommand ShowChildWindow
{
get
{
if (showChildWindow == null)
showChildWindow = new RelayCommand(ShowChildWindowFunc);
return showChildWindow;
}
} private void ShowChildWindowFunc()
{
ChildWindow1 child = new ChildWindow1();
child.Show();
var bookItem = new BookItem() { BAuthor="TestAuthor",BName="TestName" };
Messenger.Default.Send<BookItem>(bookItem);
}
#endregion
这样当运行起来的时候,我们就能看到效果了:
好了,暂时就到这里,后面我们再深入挖掘。
管窥MVVMLight Command参数绑定和事件传递的更多相关文章
- mybatis第二篇—参数绑定
不管我们在做数据库作业或者任务还是当时的仅靠jdbc来写一个管理系统的时候,sql语句需要一些参数,从而来实现模糊查询,精确查询,插入数据,更新数据和删除数据.这些参数,在mybatis里面,又该如何 ...
- 如何给html元素的onclick事件传递参数(即如何获取html标签的data-*属性)
现在做的一个小系统为了达到领导所说的很炫的效果有用到Metro UI CSS,但是因为如何给每个磁贴(div标签)的click事件传递参数折腾了蛮久(偶是菜鸟),后来终于找到一个解决方案即通过data ...
- angularjs为ng-click事件传递参数
在angularjs开发中,我们需要为ng-click事件传递一个参数. 在js中,可以接到参数: 演示:
- React事件传递参数
<button onClick={(ev) => {this.handleClick(ev,arg1,arg2,...)}} 用箭头函数,注意第一个参数一定要是事件参数.
- 将命令绑定到事件中(WPF)
绑定到指定名称控件的——>指定属性上 <i:Interaction.Triggers> <i:EventTrigger E ...
- Android按键事件传递流程(二)
5 应用层如何从Framework层接收按键事件 由3.2和4.5.4节可知,当InputDispatcher通过服务端管道向socket文件描述符发送消息后,epoll机制监听到了I/O事件, ...
- cocos2d-x jsb 防止触摸事件传递
在游戏中要实现消息弹窗,让用户点击确认,其他区域产生遮罩,阻挡下层的事件被点击到,这是个很常用的功能,在cocos2d-x中,可以通过为layer添加事件代理来实现: pDirector->ge ...
- 利刃 MVVMLight 5:绑定在表单验证上的应用
表单验证是MVVM体系中的重要一块.而绑定除了推动 Model-View-ViewModel (MVVM) 模式松散耦合 逻辑.数据 和 UI定义 的关系之外,还为业务数据验证方案提供强大而灵活的支持 ...
- 在Activity,Service,Window中监听Home键和返回键的一些思考,如何把事件传递出来的做法!
在Activity,Service,Window中监听Home键和返回键的一些思考,如何把事件传递出来的做法! 其实像按键的监听,我相信很多人都很熟练了,我肯定也不会说这些基础的东西,所以,前期,还是 ...
随机推荐
- iOS项目上传到AppStore步骤流程
1.登录developer.apple.com 2.点击member center后 进下图 3.点击certificates Identifiers进下图 4.点击Certificates进下图,首 ...
- centos创建监控宝采集器及添加插件任务
官方的说明文档很不详细操作也有点小问题,故把操作记录如下. 操作系统环境: centos 5.8 python 2.4.3 创建采集器等操作这里就不说了,见官方文档:http://blog.jiank ...
- 阿里云ECS服务器(ubuntu)下基本配置以及升级git
最近需要在阿里云服务器上远程搭建调试环境,这里把遇到的问题做一下记录: 1.ECS Linux解决SSH会话连接超时问题 用SSH客户端(我使用的Xshell)连接linux服务器时,经常会出现与服务 ...
- select_tag 选择后自动提交,并且保持选择的项
使用select来选择,,,选择就响应真是花了好大的功夫....你妹...在controller设置变量来储存选择后的值...js中如果select选择为空那么传入的值是””而不是null selec ...
- 算法(三)粒子群算法PSO的介绍
一.引言 在讲算法之前,先看两个例子: 例子一:背包问题,一个书包,一堆物品,每个物品都有自己的价值和体积,装满书包,使得装的物品价值最大. 例子二:投资问题,n个项目,第i个项目投资为ci 收益为p ...
- Swing应用开发实战系列之二:设计日期选择面板窗口
Swing本身没有提供什么华丽丽的日期时间选择控件,所以笔者就在网上搜了个第三方的jar包jdatepicker-1.3.2.jar,基于此设计了个很轻量的日期选择面板,很简单的.效果图如下所示: 代 ...
- 超链接的那些事(三): 属性target
a标签的属性之一 target 1. 定义 规定在何处打开链接文档. 如果a标签中有target属性,浏览器将会载入和显示用这个标签的 href 属性命名的.名称与这个目标吻合的框架或者窗口中 ...
- java 使用POI批量导入excel数据
一.定义 Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. 二.所需jar包: 三.简单的一个读取e ...
- 有用的MySQL语句
摘自onefish资料库 1. 计算年数你想通过生日来计算这个人有几岁了. SELECT DATE_FORMAT(FROM_DAYS(TO_DAYS(now()) - TO_DAYS(@dateofb ...
- 迅为iTOP-4412开发板Ubuntu操作系统烧写方法
本文转自:http://www.topeetboard.com Ubuntu系统烧写硬件平台:iTOP4412开发板 需要准备:串口线.读卡器.一张SD卡最好是2G(自备).另外一张卡(大于等于2G都 ...