MVVM——Model-View-ViewModel的缩写形式。
Model——可以理解为带有字段、属性的类。 View——可以理解为我们看到的UI。 View Model——在View和Model之间,起到连接作用,并且使得View和Model层分离。View Model不仅仅是Model的包装,它还包含了程序逻辑,以及
Model扩展。例如,如果Model中有一个公开属性不需要在UI上显示,此时我们不需要在View Model中去定义它。
在MVVM中,VM的地位举足轻重。使用MVVM模式具有以下几个特点:
①视图的cs文件包含极少数的代码,其核心逻辑都被放在<font style="color:#E8323C;">View Model</font>类中,从而使得程序逻辑与视图耦合度降低。
②<font style="color:#E8323C;">View Model</font>类作为<font style="color:#E8323C;">View</font>的<font style="color:#E8323C;">DataContext</font>。
③在MVVM下,所有的事件和动作都被当成命令,如按钮的点击操作,此时不是触发点击事件,而是绑定到一个点击命令,再由命令去执行对应的逻辑。
第三点很关键,因为在MVVM中,事件都被当成命令来进行处理,其中命令只能与具有Command属性的控件进行绑定。
namespace WpfApplication1{//第一步:自然是数据部分了,即Model层的实现。在这里定义了一个Person类,其中包含了2个基本的属性。public class PersonModel{public string Name { get; set; }public int Age { get; set; }}}
namespace WpfApplication1{//为了进行测试,下面创建一个静态方法来获得测试数据。public class PersonDataHelper{public static ObservableCollection<PersonModel> GetPersons(){ObservableCollection<PersonModel> samplePersons = new ObservableCollection<PersonModel>();samplePersons.Add(new PersonModel() { Name = "张三", Age = 33 });samplePersons.Add(new PersonModel() { Name = "王五", Age = 22 });samplePersons.Add(new PersonModel() { Name = "李四", Age = 35 });samplePersons.Add(new PersonModel() { Name = "LearningHard", Age = 27 });return samplePersons;}}}
namespace WpfApplication1{//第二步:实现ViewModel层,实现数据和界面之间的逻辑。在视图模型类中,包含了属性和命令,//因为在MVVM中,事件都当成命令来进行处理,其中命令只能与具有Command属性的控件进行绑定。//既然要包含命令,首先就需要实现一个命令,这里自定义的命令需要实现ICommand接口。//这里我们定义了一个QueryCommand。具体的实现代码如下所示:public class QueryCommand : ICommand{#region Fieldsprivate Action _execute;private Func<bool> _canExecute;#endregionpublic QueryCommand(Action execute) : this(execute, null){}public QueryCommand(Action execute, Func<bool> canExecute){if (execute == null)throw new ArgumentNullException("execute");_execute = execute;_canExecute = canExecute;}#region ICommand Memberpublic event EventHandler CanExecuteChanged{add{if (_canExecute != null){CommandManager.RequerySuggested += value;}}remove{if (_canExecute != null){CommandManager.RequerySuggested -= value;}}}public bool CanExecute(object parameter){return _canExecute == null ? true : _canExecute();}public void Execute(object parameter){_execute();}#endregion}}
namespace WpfApplication1{public class PersonListViewModel : INotifyPropertyChanged{#region Fieldsprivate string _searchText;private ObservableCollection<PersonModel> _resultList;#endregion#region Propertiespublic ObservableCollection<PersonModel> PersonList { get; private set; }// 查询关键字public string SearchText{get { return _searchText; }set{_searchText = value;RaisePropertyChanged("SearchText");}}// 查询结果public ObservableCollection<PersonModel> ResultList{get { return _resultList; }set{_resultList = value;RaisePropertyChanged("ResultList");}}public ICommand QueryCommand{get { return new QueryCommand(Searching, CanSearching); }}#endregion#region Constructionpublic PersonListViewModel(){PersonList = PersonDataHelper.GetPersons();_resultList = PersonList;}#endregion#region Command Handlerpublic void Searching(){ObservableCollection<PersonModel> personList = null;if (string.IsNullOrWhiteSpace(SearchText)){ResultList = PersonList;}else{personList = new ObservableCollection<PersonModel>();foreach (PersonModel p in PersonList){if (p.Name.Contains(SearchText)){personList.Add(p);}}if (personList != null){ResultList = personList;}}}public bool CanSearching(){return true;}#endregion#region INotifyPropertyChanged Memberspublic event PropertyChangedEventHandler PropertyChanged;#endregion#region Methodsprivate void RaisePropertyChanged(string propertyName){// take a copy to prevent thread issuesPropertyChangedEventHandler handler = PropertyChanged;if (handler != null){handler(this, new PropertyChangedEventArgs(propertyName));}}#endregion}}
<Window x:Class="WpfApplication1.PersonsView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:WpfApplication1"Title="PersonsView" Height="300" Width="300"><Window.DataContext><local:PersonListViewModel /></Window.DataContext><Grid><Grid.RowDefinitions><RowDefinition Height="50"/><RowDefinition Height="*"/></Grid.RowDefinitions><TextBox Grid.Row="0" Name="searchtxt" Text="{Binding Path=SearchText, Mode=TwoWay}"HorizontalAlignment="Left" Height="30" Width="280" Margin="10,0,0,0"></TextBox><Button Grid.Row="0" Name="searchBtn" Content="Search" Command="{Binding Path=QueryCommand}"Width="80" Height="30" HorizontalAlignment="Right" Margin="0,0,10,0"></Button><DataGrid Grid.Row="1" Name="datGrid"HorizontalAlignment="Center"VerticalAlignment="Top" ItemsSource="{Binding Path=ResultList}" Width="300"></DataGrid></Grid></Window>
