管窥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 解决表单被键盘遮住的问题
问题 处理表单的时候,一定会碰到的就是输入控件被键盘遮住的问题,如图: 实例 左边是普通表单,中间是2B表单,右边是文艺表单. 分析 处理这种问题无非就是2个步骤: 键盘弹出时,缩小UITableVi ...
- iOS开发笔记11:表单键盘遮挡、浮点数价格格式化显示、省市区选择器、View Debugging
1.表单键盘遮挡 应用场景为一个collectionView上有多个textfield.textView供用户填写信息. 之前输入项较少时,采取的方法比较粗暴,didSelectItemAtIndex ...
- 27个提升效率的iOS开源库推荐
DZNEmptyDataSet(UI,空表格视图解算器) PDTSimpleCalendar(UI,drop-in日历组件) MagicalRecord(实施活跃记录模式的Core Data助手) C ...
- System.Data.Entity 无法引用的问题
最近刚学MVC,跟着网上的博客学习,发现代码中有这样一句: using System.Data; using System.Data.Entity; 我项目引用的时候,也引用了System.Data. ...
- javascript 的字符串原生方法
join([分隔符])数组元素组合为字符串 toString()以字符串表示数组 reverse()数组反转--改变原数组本身 valueOf()返回数组值 <html> <head ...
- MYSQL数据库函数集合
一.数学函数 ABS(x) 返回x的绝对值 BIN(x) 返回x的二进制(OCT返回八进制,HEX返回十六进制) CEILING(x) 返回大于x的最小整数值 EXP(x) 返回值e( ...
- 观察者模式--java jdk中提供的支持
一.简介 观察者设计模式有如下四个角色 抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者.抽象主题提供一个接口,可以增加和删除观察者角色.一般用一个抽象 ...
- android中TimePicker和DatePicker的简单使用
package com.example.demo10; import java.util.Calendar; import android.support.v7.app.ActionBarActivi ...
- nyoj 284 坦克大战 简单搜索
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=284 题意:在一个给定图中,铁墙,河流不可走,砖墙走的话,多花费时间1,问从起点到终点至少 ...
- 关于hadoop 配置文件的一些实验
机器配置如下,两台机器,nn2,nn2,搭建基于QJM的高可用集群,zk集群. 如果我在yarn-site.xml中配置的nodemanager的可用资源过少,其他配置如果不一致,那么就会造成提交的j ...