接下來我們通過兩節課程使用MVVM來開發一個簡單的Demo,首先我們創建一個項目名稱WPF-22-MVVM-Demo,目錄結構如下:
我們在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,在該界面有兩部分組成:
錄入信息,將文本框和EmployeeViewMode中的Employee對象的屬性做綁定
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>
運行如下:
這節我們主要介紹MVVM項目整體結構以及UI頁面布局,并且將控件和ViewModel數據模型進行了綁定,實現了最基本DataGrid數據綁定,在接下來我們將實現增刪改查
WPF中Command綁定引用了設計模式中的命令模式(Command Pattern)