wpf之MVVM
MVVM,一言以蔽之,即使用ViewModel调用DAL层(或是其他层)来对Model进行增删查改操作,然后通过绑定和命令将数据展示到View中。
调用DAL层操作数据,没什么可说的。关于绑定,本人的上一篇文章 wpf之数据绑定基础 中已有涉及。本文将通过一个简单而完整的例子来讲述数据的展示及用户操作的绑定,且看本人慢慢道来。
Model还是依旧使用上一篇文章中的,下面是两个Model的代码。
public class ModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }
public class Person : ModelBase { private string Id; public string ID { get { return Id; } set { Id = value; OnPropertyChanged("ID"); } } private string name; public string Name { get { return name; } set { name = value; OnPropertyChanged("Name"); } } }
现在我们来准备ViewModel,首先我们要显示数据集,所以ViewModel中需要有一个Person的集合(这里用BindingList<Person>)。
下面即是读取、显示数据的代码,注数据均为虚拟的,未访问数据库。
public class ViewModel : ModelBase { private BindingList<Person> _people; public BindingList<Person> People { get { return _people ?? (_people = new BindingList<Person>()); } set { _people = value; OnPropertyChanged("People"); } } public ViewModel() { People = GetAll(); } public BindingList<Person> GetAll() { BindingList<Person> people = new BindingList<Person>(); for (int i = 1; i <= 10; i++) { people.Add(new Person() { ID = i.ToString(), Name = "Person" + i.ToString() }); } return people; } }
现在我们将数据绑定到界面,并在后台代码中设置数据源 this.DataContext = new ViewModel(),这里直接将数据源设置到整个窗体了。好了,现在数据已经可以展示在界面上了。
<ListBox Margin="10" ItemsSource="{Binding Path=People}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <StackPanel.Resources> <Style TargetType="TextBlock"> <Setter Property="Margin" Value="10 0 0 0"/> </Style> </StackPanel.Resources> <TextBlock Text="ID:"/> <TextBlock Text="{Binding Path=ID}"/> <TextBlock Text="Name:"/> <TextBlock Text="{Binding Path=Name}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
上面说过,一般我们会对数据进行增删查改的操作,目前我们看到的只是查,还有增删改需要与用户交互。下面我就展示下如何添加数据,而修改和删除则仅仅是逻辑和视图的不同而已,依葫芦画瓢即可。
为了将用户操作从后台提取到ViewModel中,需要绑定命令。于是我们可以通过委托将方法传递给自定义命令,下面是本人封装的一个简单自定义命令。事实上自定义命令只需要实现ICommand接口即可,读者自己可以根据需求去封装,不过目前很多人都使用Prism中的DelegateCommand或是将其修改为自己的。
public class CustomCommand : ICommand { private Action _executeMethod; private Func<bool> _canExecuteMethod; public CustomCommand(Action executeMethod, Func<bool> canExecuteMethod) { if (executeMethod == null) { throw new ArgumentNullException("executeMethod"); } _executeMethod = executeMethod; _canExecuteMethod = canExecuteMethod; } public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) { if (_canExecuteMethod == null) return true; return _canExecuteMethod(); } public void Execute(object parameter) { if (_executeMethod != null) _executeMethod(); } }
现在我们再向ViewModel中添加一个命令来实现数据添加的操作。由于我们要添加数据(本示例只演示一个添加操作),所以我们还需要一个临时的Person对象来绑定用户数据,然后将其添加到集合中,进而将这个集合保存到数据库。
private Person _person; public Person person { get { return _person ?? (_person = new Person()); } set { _person = value; OnPropertyChanged("person"); } } private CustomCommand _addCmd; public CustomCommand AddCmd { get { return _addCmd ?? (_addCmd = new CustomCommand(Add, CanAdd)); } } public void Add() { if (person != null) People.Add(person); } public bool CanAdd() { return People != null && person != null; }
接下来,将这个Person对象和操作绑定到界面就大功告成了。
<StackPanel Orientation="Horizontal" Margin="10"> <TextBlock Text="ID:"/> <TextBox Width="100" Text="{Binding Path=person.ID}" /> <TextBlock Text="Name:" Margin="10 0 0 0"/> <TextBox Width="100" Text="{Binding Path=person.Name}"/> <Button Content="Add" Command="{Binding Path=AddCmd}" Margin="10 0 0 0"/> </StackPanel>
下面是运行图。