1. 概述
MVVM 是WPF中常用的模式: Model View ViewModel.
其中 ViewModel 在在View 和 Model中起着双向连接的作用.
在WPF中 MVVM的运行流程如下:
2.实现
2.1 定义 Model
先定义显示所需的数据模型 Person:
namespace WPFDemo.DataBinding {
public class Person{
public string Name { get; set; }
public int Age { set; get; }
}
}
2.2 定义命令 Command
在MVVM中View通过 Command 来通知 ViewModel 进行逻辑操作. 现定义一个查询的Command:
namespace WPFDemo.DataBinding {
public class QueryCommand : ICommand {
private Action executeAction;
private Func<bool> canExecuteFun;
public QueryCommand(Action executeAction) : this(executeAction, null) {
}
public QueryCommand(Action executeAction, Func<bool> canExecuteFun) {
this.executeAction = executeAction ?? throw new ArgumentNullException(nameof(executeAction));
this.canExecuteFun = canExecuteFun;
}
public void Execute(object parameter) {
executeAction();
}
public bool CanExecute(object parameter) {
return canExecuteFun == null ? true : canExecuteFun();
}
public event EventHandler CanExecuteChanged {
add {
if (canExecuteFun != null) {
CommandManager.RequerySuggested += value;
}
}
remove {
if (canExecuteFun != null) {
CommandManager.RequerySuggested -= value;
}
}
}
}
}
2.3 定义ViewModel
在 ViewModel 中数据发生变化需要自动显示在View上, 所以需要实现 INotifyPropertyChanged
接口
namespace WPFDemo.DataBinding {
public class DataBindingViewModule : INotifyPropertyChanged {
//保存用户输入的数据
private string searchText;
public string SearchText {
get => searchText;
set {
searchText = value;
RaisePropertyChanged(nameof(SearchText));
}
}
//查询的结果
private ObservableCollection<Person> resultList;
public ObservableCollection<Person> ResultList {
get => resultList;
private set {
resultList = value;
RaisePropertyChanged(nameof(ResultList));
}
}
// 基础数据
public ObservableCollection<Person> Persons { get; private set; }
//查询命令 绑定到按钮
public ICommand QueryCommand {
get => new QueryCommand(Searching, CanSearch);
}
public DataBindingViewModule() {
Persons = new ObservableCollection<Person> {
new Person() {Name = "zhangsan", Age = 11},
new Person() {Name = "lisi", Age = 10},
new Person() {Name = "wangwu", Age = 11}
};
ResultList = Persons;
}
// 搜索逻辑
private void Searching() {
if (string.IsNullOrEmpty(SearchText)) {
ResultList = Persons;
} else {
ObservableCollection<Person> collection = new ObservableCollection<Person>();
foreach (var person in Persons) {
if (person.Name.Contains(SearchText)) {
collection.Add(person);
}
}
if (collection.Count != 0) {
ResultList = collection;
}
}
}
//是否可搜索
private bool CanSearch() {
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void RaisePropertyChanged(string propertyName) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
2.4 定义界面
界面很简单, 一个表格显示所有的信息, 一个输入框让用户输入查询条件, 点击查询按钮 进行结果查询, 结果自动显示更新到界面.
<Page x:Class="WPFDemo.DataBinding.DataBindingPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFDemo.DataBinding"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="DataBindingPage">
<Page.DataContext>
<local:DataBindingViewModule/>
</Page.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox
x:Name="SearchTb" Text="{Binding Path=SearchText, Mode=TwoWay}"
HorizontalAlignment="Center" VerticalAlignment="Center"
Grid.Row="0" Grid.Column="0" Width="320"/>
<Button
x:Name="QueryBtn" Command="{Binding QueryCommand}"
Height="32" Width="48" Content="Query" Grid.Row="0" Grid.Column="1"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
<DataGrid
x:Name="ResultDg" ItemsSource="{Binding Path=ResultList}"
Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" Width="400" IsReadOnly="True"
VerticalAlignment="Top" HorizontalAlignment="Center">
</DataGrid>
</Grid>
</Page>
2.5 运行效果
3. 项目代码
此项目代码在此:
WPFDemo/DataBinding at master · Dev-Wiki/WPFDemo]
(https://github.com/Dev-Wiki/WPFDemo/tree/master/DataBinding)