⾛进WPF之MVVM完整案例
学习WPF如果不学MVVM,仿佛缺少了灵魂。那什么是MVVM呢?为什么要学MVVM呢,本以⼀个简单的增删改查的⼩例⼦,简述MVVM的基本知识及如何通过进⾏MVVM架构的程序开发,仅供学习分享使⽤,如有不⾜之处,还请指正。
什么是MVVM?
MVVM是Model-View-ViewModel的简写。它本质上就是MVC (Model-View- Controller)的改进版。即模型-视图-视图模型。分别定义如下:
【模型】指的是后端传递的数据。
【视图】指的是所看到的页⾯。
【视图模型】mvvm模式的核⼼,它是连接view和model的桥梁。它有两个⽅向:
⼀是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页⾯。实现的⽅式是:数据绑定。
⼆是将【视图】转化成【模型】,即将所看到的页⾯转化成后端的数据。实现的⽅式是:DOM 事件监听。这两个⽅向都实现的,我们称之为数据的双向绑定。
MVVM⽰意图如下所⽰:
安装MvvmLight插件
项⽬名称右键-->管理NuGet程序包-->搜索MvvmLight-->安装。如下所⽰:
弹出接受许可证窗⼝,点击【接受】如下所⽰:
MvvmLight安装成功后,⾃动引⽤需要的第三⽅库,并默认⽣成⽰例内容,有些不需要的需要删除,如下所⽰:
MVVM⽰例截图
主要通过MVVM实现数据的CRUD【增删改查】基础操作,如下所⽰:
MVVM开发步骤
1. 创建Model层
本例主要是对学⽣信息的增删改查,所以创建Student模型类,如下所⽰: 1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading.Tasks;
6
7namespace WpfApp3.Models
8 {
9///<summary>
10///学⽣类
11///</summary>
12public class Student
app开发实例
13 {
14///<summary>
15///唯⼀标识
16///</summary>
17public int Id { get; set; }
18
19///<summary>
20///学⽣姓名
21///</summary>
22public string Name { get; set; }
23
24///<summary>
25///年龄
26///</summary>
27public int Age { get; set; }
28
29///<summary>
30///班级
31///</summary>
32public string Classes { get; set; }
33 }
34 }
2. 创建DAL层
为了简化⽰例,模拟数据库操作,构建基础数据,如下所⽰:
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading.Tasks;
6using WpfApp3.Models;
7
8namespace WpfApp3.DAL
9 {
10public class LocalDb
11 {
12private List<Student> students;
13
14public LocalDb() {
15 init();
16 }
17
18///<summary>
19///初始化数据
20///</summary>
21private void init() {
22 students = new List<Student>();
23for (int i = 0; i < 30; i++)
24 {
25 students.Add(new Student()
26 {
27 Id=i,
28 Name=string.Format("学⽣{0}",i),
29 Age=new Random(i).Next(0,100),
30 Classes=i%2==0?"⼀班":"⼆班"
31 });
32 }
33 }
34
35///<summary>
36///查询数据
37///</summary>
38///<returns></returns>
39public List<Student> Query()
40 {
41return students;
42 }
43
44///<summary>
45///按名字查询
46///</summary>
47///<param name="name"></param>
48///<returns></returns>
49public List<Student> QueryByName(string name)
50 {
51return students.Where((t) => t.Name.Contains(name)).ToList();//FindAll((t) => t.Name.Contains(name));
52 }
53
54public Student QueryById(int Id)
55 {
56var student = students.FirstOrDefault((t) => t.Id == Id);
57if (student != null)
58 {
59return new Student() {
60 Id=student.Id,
61 Name=student.Name,
62 Age=student.Age,
63 Classes=student.Classes
64 };
65 }
66return null;
67 }
68
69
70///<summary>
71///新增学⽣
72///</summary>
73///<param name="student"></param>
74public void AddStudent(Student student)
75 {
76if (student != null)
77 {
78 students.Add(student);
79 }
80 }
81
82///<summary>
83///删除学⽣
84///</summary>
85///<param name="Id"></param>
86public void DelStudent(int Id)
87 {
88var student = students.FirstOrDefault((t) => t.Id == Id); //students.Find((t) => t.Id == Id);
89if (student != null)
90 {
91 students.Remove(student);
92 }
93
94 }
95 }
96
97
98 }
3. 创建View层
View层与⽤户进⾏交互,⽤户数据的展⽰,及事件的响应。在本例中,View层主要有数据查询展⽰,新增及编辑页⾯。
在View层,主要是命令的绑定,及数据的绑定。
1. 在DataGridTextColumn中通过Binding="{Binding Id}"的形式绑定要展⽰的列属性名。
2. 在Button按钮上通过Command="{Binding AddCommand}"的形式绑定要响应的命令。
3. 在TextBox⽂本框中通过Text="{Binding Search}"的形式绑定查询条件属性。
数据展⽰窗⼝,如下所⽰:
1<Window x:Class="WpfApp3.MainWindow"
2 xmlns="schemas.microsoft/winfx/2006/xaml/presentation"
3 xmlns:x="schemas.microsoft/winfx/2006/xaml"
4 xmlns:d="schemas.microsoft/expression/blend/2008"
5 xmlns:mc="/markup-compatibility/2006"
6 xmlns:local="clr-namespace:WpfApp3"
7 mc:Ignorable="d"
8 Title="MainWindow" Height="450" Width="800">
9<Grid>
10<Grid.RowDefinitions>
11<RowDefinition Height="80"></RowDefinition>
12<RowDefinition Height="*"></RowDefinition>
13</Grid.RowDefinitions>
14<StackPanel Orientation="Horizontal" Grid.Row="0" Margin="5" VerticalAlignment="Center">
15<TextBlock Text="姓名:" Margin="10" Padding="5"></TextBlock>
16<TextBox x:Name="sname" Text="{Binding Search}" Width="120" Margin="10" Padding="5"></TextBox>
17<Button x:Name="btnQuery" Content="查询" Margin="10" Padding="5" Width="80" Command="{Binding QueryCommand}"></Button>
18<Button x:Name="btnReset" Content="重置" Margin="10" Padding="5" Width="80" Command="{Binding ResetCommand}"></Button>
19<Button x:Name="btnAdd" Content="创建" Margin="10" Padding="5" Width="80" Command="{Binding AddCommand}"></Button>
20</StackPanel>
21<DataGrid x:Name="dgInfo" Grid.Row="1" AutoGenerateColumns="False" CanUserAddRows="False" CanUserSortColumns="False" Margin="10" ItemsSource="{Binding GridModelList}">
22<DataGrid.Columns>
23<DataGridTextColumn Header="Id" Width="100" Binding="{Binding Id}"></DataGridTextColumn>
24<DataGridTextColumn Header="姓名" Width="100" Binding="{Binding Name}"></DataGridTextColumn>
25<DataGridTextColumn Header="年龄" Width="100" Binding="{Binding Age}"></DataGridTextColumn>
26<DataGridTextColumn Header="班级" Width="100" Binding="{Binding Classes}"></DataGridTextColumn>
27<DataGridTemplateColumn Header="操作" Width="*">
28<DataGridTemplateColumn.CellTemplate>
29<DataTemplate>
30<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
31<Button x:Name="edit" Content="编辑" Width="60" Margin="3" Height="25" CommandParameter="{
Binding Id}" Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource Mode=FindAncestor, An 32<Button x:Name="delete" Content="删除" Width="60" Margin="3" Height="25" CommandParameter="{Binding Id}" Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncesto 33</StackPanel>
34</DataTemplate>
35</DataGridTemplateColumn.CellTemplate>
36</DataGridTemplateColumn>
37</DataGrid.Columns>
38</DataGrid>
39</Grid>
40</Window>
新增及编辑页⾯,如下所⽰:
1<Window x:Class="WpfApp3.Views.StudentWindow"
2 xmlns="schemas.microsoft/winfx/2006/xaml/presentation"
3 xmlns:x="schemas.microsoft/winfx/2006/xaml"
4 xmlns:d="schemas.microsoft/expression/blend/2008"
5 xmlns:mc="/markup-compatibility/2006"
6 xmlns:local="clr-namespace:WpfApp3.Views"
7 mc:Ignorable="d"
8 Title="StudentWindow" Height="440" Width="500" AllowsTransparency="False" WindowStartupLocation="CenterScreen" WindowStyle="None">
9<Grid>
10<Grid.RowDefinitions>
11<RowDefinition Height="60"></RowDefinition>
12<RowDefinition></RowDefinition>
13<RowDefinition Height="60"></RowDefinition>
14</Grid.RowDefinitions>
15<TextBlock FontSize="30" Margin="10">修改学⽣信息</TextBlock>
16<StackPanel Grid.Row="1" Orientation="Vertical">
17<TextBlock FontSize="20" Margin="10" Padding="5">姓名</TextBlock>
18<TextBox x:Name="txtName" FontSize="20" Padding="5" Text="{Binding Model.Name}"></TextBox>
19<TextBlock FontSize="20" Margin="10" Padding="5">年龄</TextBlock>
20<TextBox x:Name="txtAge" FontSize="20" Padding="5" Text="{Binding Model.Age}"></TextBox>
21<TextBlock FontSize="20" Margin="10" Padding="5">班级</TextBlock>
22<TextBox x:Name="txtClasses" FontSize="20" Padding="5" Text="{Binding Model.Classes}"></TextBox>
23</StackPanel>
24<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
25<Button x:Name="btnSave" Content="保存" Margin="10" FontSize="20" Width="100" Click="btnSave_Click"></Button> 26<Button x:Name="btnCancel" Content="取消" Margin="10" FontSize="20" Width="100" Click="btnCancel_Click"></Button> 27</StackPanel>
28</Grid>
29</Window>
3. 创建ViewModel层
ViewModel层是MVVM的核⼼所在,起到承上启下的作⽤。ViewModel需要继承GalaSoft.MvvmLight.ViewModelBase基类。ViewModel中属性实现数据的绑定,命令实现⽤户交互的响应。如下所⽰:
1using GalaSoft.MvvmLight;
2using GalaSoft.MvvmLight.Command;
3using System.Collections.Generic;
4using System.Collections.ObjectModel;
5using System.Linq;
6using System.Windows;
7using WpfApp3.DAL;
8using WpfApp3.Models;
9using WpfApp3.Views;
10
11namespace WpfApp3.ViewModel
12 {
13///<summary>
14///
15///</summary>
16public class MainViewModel : ViewModelBase
17 {
18#region属性及构造函数
19
20private LocalDb localDb;
21
22private ObservableCollection<Student> gridModelList;
23
24public ObservableCollection<Student> GridModelList
25 {
26get { return gridModelList; }
27set
28 {
29 gridModelList = value;
30 RaisePropertyChanged();
31 }
32 }
33
34///<summary>
35///查询条件
36///</summary>
37private string search;
38
39public string Search
40 {
41get { return search; }
42set
43 {
44 search = value;
45 RaisePropertyChanged();
46 }
47 }
48
49
50///<summary>
51///
52///</summary>
53public MainViewModel()
54 {
55 localDb = new LocalDb();
56 QueryCommand = new RelayCommand(this.Query);
57 ResetCommand = new RelayCommand(this.Reset);
58 EditCommand = new RelayCommand<int>(this.Edit);
59 DeleteCommand = new RelayCommand<int>(this.Delete);
60 AddCommand = new RelayCommand(this.Add);
61 }
62
63#endregion
64
65#region command
66
67///<summary>
68///查询命令
69///</summary>
70public RelayCommand QueryCommand { get; set; }
71
72///<summary>
73///重置命令
74///</summary>
75public RelayCommand ResetCommand { get; set; }
76
77///<summary>
78///编辑
79///</summary>
80public RelayCommand<int> EditCommand { get; set; }
81
82///<summary>
83///删除
84///</summary>
85public RelayCommand<int> DeleteCommand { get; set; }
86
87///<summary>
88///新增
89///</summary>
90public RelayCommand AddCommand { get; set; }
91
92#endregion
93
94public void Query()
95 {
96 List<Student> students;
97if (string.IsNullOrEmpty(search))
98 {
99 students = localDb.Query();
100 }
101else
102 {
103 students = localDb.QueryByName(search);
104 }
105
106 GridModelList = new ObservableCollection<Student>();
107if (students != null)
108 {
109 students.ForEach((t) =>
110 {
111 GridModelList.Add(t);
112 });
113 }
114 }
115
116///<summary>
117///重置
118///</summary>
119public void Reset()
120 {
121this.Search = string.Empty;
122this.Query();
123 }
124
125///<summary>
126///编辑
127///</summary>
128///<param name="Id"></param>
129public void Edit(int Id)
130 {
131var model = localDb.QueryById(Id);
132if (model != null)
133 {
134 StudentWindow view = new StudentWindow(model);
135var r = view.ShowDialog();
136if (r.Value)
137 {
138var newModel = GridModelList.FirstOrDefault(t => t.Id == model.Id);
139if (newModel != null)
140 {
141 newModel.Name = model.Name;
142 newModel.Age = model.Age;
143 newModel.Classes = model.Classes;
144 }
145this.Query();
146 }
147 }
148 }
149
150///<summary>
151///删除
152///</summary>
153///<param name="Id"></param>
154public void Delete(int Id)
155 {
156var model = localDb.QueryById(Id);
157if (model != null)
158 {
159var r = MessageBox.Show($"确定要删除吗【{model.Name}】?","提⽰",MessageBoxButton.YesNo); 160if (r == MessageBoxResult.Yes)
161 {
162 localDb.DelStudent(Id);
163this.Query();
164 }
165 }
166 }
167
168///<summary>
169///新增
170///</summary>
171public void Add()
172 {
173 Student model = new Student();
174 StudentWindow view = new StudentWindow(model);
175var r = view.ShowDialog();
176if (r.Value)
177 {
178 model.Id = GridModelList.Max(t => t.Id) + 1;
179 localDb.AddStudent(model);
180this.Query();
181 }
182 }
183 }
184 }
4. 数据上下⽂
当各个层分别创建好后,那如何关联起来呢?答案就是DataContext【数据上下⽂】。
查询页⾯上下⽂,如下所⽰:
1namespace WpfApp3
2 {
3///<summary>
4/// MainWindow.xaml 的交互逻辑
5///</summary>
6public partial class MainWindow : Window
7 {
8public MainWindow()
9 {
10 InitializeComponent();
11 MainViewModel viewModel = new MainViewModel();
12 viewModel.Query();
13this.DataContext = viewModel;
14 }
15 }
16 }
新增页⾯上下⽂,如下所⽰:
1namespace WpfApp3.Views
2 {
3///<summary>
4/// StudentWindow.xaml 的交互逻辑
5///</summary>
6public partial class StudentWindow : Window
7 {
8public StudentWindow(Student student)
9 {
10 InitializeComponent();
11this.DataContext = new
12 {
13 Model = student
14 };
15 }
16
17private void btnSave_Click(object sender, RoutedEventArgs e)
18 {
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论