前言框架
因为在实际项目中,业务功能的增长致使软件开发规模在逐渐变大,因此我准备找个Silverlight框架来组织当前项目中的文件,以期可以让后续的业务功能增添和维护更加容易一些。无心中,我在这篇文章中看到了当前Silverlight下全部的框架的评测:Discover and compare existing MVVM frameworks !,当我看到MvvmLight toolkit在各方面都比较完备的时候,因而决定选择这个框架:less
在Codeplex网站上,下载了MVVM Light Toolkit V4 RTM这个版本,由于我用的是vs2010,因此我下载了支持当前机器IDE的版本。mvvm
新建项目,选择MvvmLight(SL4),以后咱们就能够看到项目结构了:网站
其中:this
Design文件夹中的文件主要提供设计时运行支持url
Model文件夹则放置了富实体模型设计
Skins文件夹则放置了样式文件定义3d
ViewModel文件夹则放置了ViewModel对象,其实MainViewModel和MainPage是一对一的(ViewMoel-View)关系.两者的映射经过ViewModelLocator进行。code
MainPage.xaml就是咱们的视图页面orm
下面咱们就以例子来演示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
这样当运行起来的时候,咱们就能看到效果了:
好了,暂时就到这里,后面咱们再深刻挖掘。