MVVM模式大家应该不陌生吧,陌生的快来看看,可是WPF/Silverlight开发中,必备的设计模式。MVVM模式解决了,我们在开发WPF/Silverlight应用程序过程中产生的业务层、表示层比较混乱问题,使表示层和业务层完全分离。早在2005年,John Gossman写了一篇关于Model-View-ViewModel模式的博文,这种模式被他所在的微软的项目组用来创建Expression Blend。
从上图可以看出来,View表示层就是我们通常的XAML,用来表示前台界面,ViewModel视图模块层的作用用来连接业务逻辑和视图层的关键部分,通常我们发出的命令或者事件都是通过这层传送给业务逻辑层的,Model就是我们的实际数据,业务逻辑代码等。
下面我们用一个Silverlight简单例子来讲解MVVM模式
这个程序就是实现简单查询,输入ID号,查询符合结果的内容
新建一个Silverlight项目,并按照下图新建目录
Command我们用来存放查询用的命令,Model我们用来存放数据,View我们用来存放显示查询的UserControl,ViewModel我们用来存放查询的ViewModel
我们先建立Model层用来存储访问要查询的数据
1 2 3 4 5 6 public class DataItem { public int ID { get ; set ; } public string Name { get ; set ; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public static class DataDemo { private static Collection<DataItem> _DataList = null ; public static Collection<DataItem> DataList { get { if (_DataList == null ) { _DataList = InitDataList(); } return _DataList; } } private static Collection<DataItem> InitDataList() { Collection<DataItem> lists = new Collection<DataItem>(); for ( int i = 0; i < 100; i++) { DataItem item = new DataItem(); item.ID = i + 1; item.Name = "例子" + (i + 1); lists.Add(item); } return lists; } }接下来,我们新建UserControl用来表示查询的页面(View)
1 2 3 4 5 6 7 8 9 10 11 12 < UserControl x:Class = "MVVMDemo.View.QueryData" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local = "clr-namespace:MVVMDemo.ViewModel" mc:Ignorable = "d" Height = "256" Width = "256" > < Grid x:Name = "LayoutRoot" > < Button x:Name = "btnSearch" Height = "24" HorizontalAlignment = "Left" Margin = "164,8,0,0" VerticalAlignment = "Top" Width = "84" Content = "搜索" /> < TextBox x:Name = "txtKeyword" Height = "24" HorizontalAlignment = "Left" Margin = "8,8,0,0" VerticalAlignment = "Top" Width = "152" TextWrapping = "Wrap" d:LayoutOverrides = "HorizontalAlignment" /> < TextBox x:Name = "txtResult" HorizontalAlignment = "Left" Margin = "8,36,0,8" Width = "240" TextWrapping = "Wrap" d:LayoutOverrides = "VerticalAlignment" /> </ Grid > </ UserControl >到这里我们已经建好了Model,View层,接下来,我们建立ViewModel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 public class QueryDataViewModel : INotifyPropertyChanged { #region 变量 /// <summary> /// 查询的数据 /// </summary> private Collection<DataItem> _DataList = null ; /// <summary> /// 查询命令 /// </summary> private ICommand _QueryCommand = null ; /// <summary> /// 搜索关键字 /// </summary> private string _SearchText = string .Empty; /// <summary> /// 搜索结果 /// </summary> private string _SearchResult = string .Empty; #endregion #region 属性 /// <summary> /// 搜索关键字 /// </summary> public string SearchText { get { return this ._SearchText; } set { this ._SearchText = value; if ( this .PropertyChanged != null ) this .PropertyChanged( this , new PropertyChangedEventArgs( "SearchText" )); } } /// <summary> /// 搜索结果 /// </summary> public string SearchResult { get { return this ._SearchResult; } set { this ._SearchResult = value; if ( this .PropertyChanged != null ) this .PropertyChanged( this , new PropertyChangedEventArgs( "SearchResult" )); } } /// <summary> /// 查询命令 /// </summary> public ICommand QueryCommand { get { return _QueryCommand; } } #endregion #region 构造函数 public QueryDataViewModel(Collection<DataItem> dataList) { this ._DataList = dataList; _QueryCommand = new QueryDataCommand( this ); } #endregion #region 方法 /// <summary> /// 查询数据 /// </summary> public void QueryData() { if (! string .IsNullOrEmpty( this .SearchText)) { DataItem dataItem = null ; foreach (DataItem item in this ._DataList) { if (item.ID.ToString() == this .SearchText) { dataItem = item; break ; } } if (dataItem != null ) { this .SearchResult = string .Format( "ID:{0}/nName:{1}" , dataItem.ID, dataItem.Name); } } } #endregion #region INotifyPropertyChanged 成员 public event PropertyChangedEventHandler PropertyChanged; #endregion }这是一个很简单的ViewModel,我们定义了两个属性,SearchText表示查询关键字,SearchResult表示查询结果,QueryCommand表示查询命令,后面我们会和View绑定。QueryDataCommand还没有实现,接下来我们创建QueryCommand
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class QueryDataCommand : ICommand { private QueryDataViewModel _QueryDataViewModel; public QueryDataCommand(QueryDataViewModel queryDataViewModel) { this ._QueryDataViewModel = queryDataViewModel; } #region ICommand 成员 public bool CanExecute( object parameter) { return true ; } public event EventHandler CanExecuteChanged { add { } remove { } } public void Execute( object parameter) { this ._QueryDataViewModel.QueryData(); } #endregion }到目前为止,ViewModel已经建立完成。我们将ViewModel绑定到ViewView的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public partial class QueryData : UserControl { private QueryDataViewModel _QueryDataViewModel = null ; /// <summary> /// 构造函数 /// </summary> public QueryData() { InitializeComponent(); this ._QueryDataViewModel = new QueryDataViewModel(MVVMDemo.DataDemo.DataList); base .DataContext = this ._QueryDataViewModel; this .btnSearch.Click += new RoutedEventHandler(btnSearch_Click); } /// <summary> /// 点击事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void btnSearch_Click( object sender, RoutedEventArgs e) { if ( this ._QueryDataViewModel != null ) { this ._QueryDataViewModel.SearchText = this .txtKeyword.Text; this ._QueryDataViewModel.QueryCommand.Execute( null ); } } }因为Silverlight没有Command,我们只能采用这个方法调用Command,wpf则可以在xaml里面直接绑定这个命令前台xaml我们把输入框,后结果框绑定输入框
1 2 输入框 Text="{Binding SearchText,Mode=TwoWay}" 结果框 Text="{Binding SearchResult,Mode=OneWay}"我们把View放到页面上
1 2 3 4 5 6 7 8 9 10 < UserControl x:Class = "MVVMDemo.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local = "clr-namespace:MVVMDemo.View" mc:Ignorable = "d" Height = "256" Width = "256" > < Grid > < local:QueryData ></ local:QueryData > </ Grid > </ UserControl >到目前为止,MVVM最简单的例子已经建立完成。我们发现表示层和业务逻辑层从此实现了分离,同时,我们在单元测试上也可以剥离表示层进行。
原创文章,转载请注明: 转载自.NET开发者
本文链接地址: MVVM(Model-View-ViewModel)实例讲解
ShareThis