WPF-21 基于MVVM员工管理-01

接下来我们通过两节课程使用MVVM来开发一个简单的Demo,首先我们创建一个项目名称WPF-22-MVVM-Demo,目录结构如下:

WPF-21 基于MVVM员工管理-01

我们在Models文件下创建Employee类并让该类实现INotifyPropertyChanged接口,该类中定义编号、姓名和角色三个基本属性.

using System;using System.ComponentModel;using System.Runtime.CompilerServices;namespace WPF_22_MVVM_Demo.Models{    public class Employee : INotifyPropertyChanged    {        private string no = String.Empty;        public string No        {            get            {                return no;            }            set            {                if (value != this.no)                {                    no = value;                    NotifyPropertyChanged();                }            }        }        private string name = String.Empty;        public string Name        {            get            {                return name;            }            set            {                if (value != this.name)                {                    this.name = value;                    NotifyPropertyChanged();                }            }        }        private string role = String.Empty;        public string Role        {            get            {                return role;            }            set            {                if (value != this.role)                {                    this.role = value;                    NotifyPropertyChanged();                }            }        }        public event PropertyChangedEventHandler? PropertyChanged;        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")        {            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));        }    }}

在Models文件下定义服务EmployeeService,该类可以包含一些常用业务操作,例如:对远程api调用操作远程数据库以及本地数据库操作等,在该例子中,我们对一个内存对象集合实现增删改查操作

using System.Collections.Generic;using System.Linq;namespace WPF_22_MVVM_Demo.Models{    public class EmployeeService    {        private static List<Employee> _employees = null!;        public EmployeeService()        {            _employees = new List<Employee>()            {                new Employee()                {                    No="800001",                    Name="张三丰",                    Role="武当派掌门人"                },                new Employee()                {                    No="800002",                    Name="乔峰",                    Role="乞丐掌门人"                },            };        }        public List<Employee> GetEmployees()        {            return _employees;        }    }}

在Commands文件夹下定义DelegateCommand

using System;using System.Windows.Input;namespace WPF_22_MVVM_Demo.Commands{    public class DelegateCommand : ICommand    {        private Action _execute;        private Func<bool> _canExecute;        public DelegateCommand(Action executeMethod)        {            _execute = executeMethod;        }        public DelegateCommand(Action executeMethod, Func<bool> canExecute)            : this(executeMethod)        {            this._canExecute = canExecute;        }        public event EventHandler CanExecuteChanged;        public bool CanExecute(object parameter)        {            return true;        }               public void Execute(object parameter)        {            _execute();        }    }}
在ViewModes文件加下创建EmployeeViewMode,同时该类实现INotifyPropertyChanged接口,该类引用了Employee 实体(用来绑定到UI页面)和EmployeeService服务以及DelegateCommand 类
using System;using System.Collections.ObjectModel;using System.ComponentModel;using System.Runtime.CompilerServices;using System.Windows.Input;using WPF_22_MVVM_Demo.Commands;using WPF_22_MVVM_Demo.Models;namespace WPF_22_MVVM_Demo.ViewModes{    public class EmployeeViewMode : INotifyPropertyChanged    {        public event PropertyChangedEventHandler? PropertyChanged;        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")        {            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));        }        EmployeeService employeeService;        public EmployeeViewMode()        {            employeeService = new EmployeeService();            BindData();            Employee = new Employee();        }        private Employee employee;        public Employee Employee        {            get { return employee; }            set { employee = value;NotifyPropertyChanged(); }        }        private ObservableCollection<Employee> employeeList;        public ObservableCollection<Employee> EmployeeList        {            get            {                return employeeList;            }            set            {                employeeList = value;                NotifyPropertyChanged();            }        }        /// <summary>        ///消息提示        /// </summary>        public string Message        {            get;            set;        }        /// <summary>        /// DataGrid绑定数据        /// </summary>        public void BindData()        {            EmployeeList = new ObservableCollection<Employee>(employeeService.GetEmployees());        }     }}

在Views文件加下创建EmployeeView.xaml,将窗体的DataContext指向EmployeeViewMode,在该界面有两部分组成:

  1. 录入信息,将文本框和EmployeeViewMode中的Employee对象的属性做绑定
  2. DataGrid展示数据列表,将控件的ItemsSource属性绑定EmployeeViewMode对象中的EmployeeList属性
<UserControl x:Class="WPF_22_MVVM_Demo.Views.EmployeeView"             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"              mc:Ignorable="d">    <Grid>        <Grid.RowDefinitions>            <RowDefinition Height="0.1*"></RowDefinition>            <RowDefinition Height="0.1*"></RowDefinition>            <RowDefinition Height="0.1*"></RowDefinition>            <RowDefinition Height="0.1*"></RowDefinition>            <RowDefinition Height="0.6*"></RowDefinition>        </Grid.RowDefinitions>        <Grid.ColumnDefinitions>            <ColumnDefinition Width="0.35*"></ColumnDefinition>            <ColumnDefinition Width="0.65*"></ColumnDefinition>        </Grid.ColumnDefinitions>        <TextBlock Grid.Row="0" Grid.Column="0" Margin="10">员工编号</TextBlock>        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=Employee.No}" Width="150" HorizontalAlignment="Left" Margin="10"/>        <TextBlock Grid.Row="1" Grid.Column="0" Margin="10">员工姓名</TextBlock>        <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path=Employee.Name}" Width="150" HorizontalAlignment="Left" Margin="10"></TextBox>        <TextBlock Grid.Row="2" Grid.Column="0" Margin="10">角色</TextBlock>        <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=Employee.Role}" Width="150" HorizontalAlignment="Left" Margin="10"></TextBox>        <StackPanel Grid.Row="3" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">            <Grid>                <Grid.RowDefinitions>                    <RowDefinition></RowDefinition>                </Grid.RowDefinitions>                <Grid.ColumnDefinitions>                    <ColumnDefinition></ColumnDefinition>                    <ColumnDefinition></ColumnDefinition>                    <ColumnDefinition></ColumnDefinition>                    <ColumnDefinition></ColumnDefinition>                </Grid.ColumnDefinitions>            </Grid>            <Button Content="新增" Width="100" Height="30" Margin="2"></Button>            <Button Content="修改" Width="100" Height="30" Margin="2"></Button>            <Button Content="删除" Width="100" Height="30" Margin="2"></Button>            <Button Content="查询" Width="100" Height="30" Margin="2"></Button>        </StackPanel>        <DataGrid Grid.Row="4" Grid.ColumnSpan="2" Name="empGrid" AutoGenerateColumns="False" ItemsSource="{Binding Path=EmployeeList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">            <DataGrid.Columns>                <DataGridTextColumn Header="员工编号" Width="0.3*" Binding="{Binding Path=No,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn>                <DataGridTextColumn Header="姓名" Width="0.3*" Binding="{Binding Path=Name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn>                <DataGridTextColumn Header="角色" Width="0.3*" Binding="{Binding Path=Role,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn>            </DataGrid.Columns>        </DataGrid>    </Grid></UserControl>
using System.Windows.Controls;using WPF_22_MVVM_Demo.ViewModes;namespace WPF_22_MVVM_Demo.Views{    /// <summary>    /// Interaction logic for EmployeeView.xaml    /// </summary>    public partial class EmployeeView : UserControl    {        public EmployeeView()        {            InitializeComponent();            this.DataContext = new EmployeeViewMode();        }    }}

在MainWindow.xaml窗体中引用EmployeeView

<Window x:Class="WPF_22_MVVM_Demo.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"        xmlns:EmpView="clr-namespace:WPF_22_MVVM_Demo.Views"        mc:Ignorable="d"        Title="员工管理" Height="450" Width="500">    <StackPanel>        <EmpView:EmployeeView></EmpView:EmployeeView>    </StackPanel></Window>

运行如下:

WPF-21 基于MVVM员工管理-01

这节我们主要介绍MVVM项目整体结构以及UI页面布局,并且将控件和ViewModel数据模型进行了绑定,实现了最基本DataGrid数据绑定,在接下来我们将实现增删改查
WPF中Command绑定引用了设计模式中的命令模式(Command Pattern)