23

WPF中的MVVM实现

 4 years ago
source link: http://blog.devwiki.net/index.php/2020/02/12/mvvm-in-wpf.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1. 概述

MVVM 是WPF中常用的模式: Model - View - ViewModel.

其中 ViewModel 在在View 和 Model中起着双向连接的作用.

eAviQnF.png!web

在WPF中 MVVM的运行流程如下:

Nniqeqy.png!web

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 运行效果

AR3uyeB.gif

3. 项目代码

此项目代码在此:

WPFDemo/DataBinding at master · Dev-Wiki/WPFDemo]( https://github.com/Dev-Wiki/WPFDemo/tree/master/DataBinding)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK