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)