⾛进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小时内删除。