WPF MVVM模式实现DataGrid编辑

本文是一个MVVM模式开发的基础教程,完全手写实现,未借助三方框架,适用于初学者

要实现DataGrid的编辑,步骤如下:

1、创建两个窗口,第一个窗口用于显示DataGrid,

布局如下:

这个界面上我们放置了一个DataGrid控件,并增加了三列,前面两列用于显示数据,最后一列用于编辑命令。

MainWindow.xaml

复制代码
 1 <Window x:Class="WPFDataGridEditDemo.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WPFDataGridEditDemo"
 7         mc:Ignorable="d"
 8         Title="MainWindow" Height="450" Width="800">
 9     <Grid>
10         <DataGrid x:Name="datagrid" ItemsSource="{Binding StudentCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False"
11           CanUserAddRows="False" VerticalScrollBarVisibility="Hidden" IsReadOnly="True" Margin="20">
12             <DataGrid.Columns>
13                 <DataGridTextColumn Header="学号" Width="60" Binding="{Binding ID}"/>
14                 <DataGridTextColumn Header="姓名" Width="*" Binding="{Binding Name}"/>
15                 <DataGridTemplateColumn Header="操作" Width="120">
16                     <DataGridTemplateColumn.CellTemplate>
17                         <DataTemplate>
18                             <StackPanel Orientation="Horizontal">
19                                 <TextBlock Margin="0,0,5,0">
20                                     <Hyperlink Command="{Binding EditCommand}" CommandParameter="{Binding ElementName=datagrid,Path=SelectedItem}">编辑</Hyperlink>
21                                 </TextBlock>
22                             </StackPanel>
23                         </DataTemplate>
24                     </DataGridTemplateColumn.CellTemplate>
25                 </DataGridTemplateColumn>
26             </DataGrid.Columns>
27         </DataGrid>
28     </Grid>
29 </Window>

2、创建一个编辑窗口,这个窗口用于编辑字段值

DataEditView.xaml

复制代码
 1 <Window x:Class="WPFDataGridEditDemo.Views.DataEditView"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WPFDataGridEditDemo.Views"
 7         mc:Ignorable="d"
 8         Title="DataEditView" Height="450" Width="800">
 9     <Grid>
10         <Border>
11             <Grid Background="Transparent">
12                 <TabControl BorderThickness="0" Margin="0,5">
13                     <TabItem Header="学生信息" FontSize="12">
14                         <Grid>
15                             <Grid.ColumnDefinitions>
16                                 <ColumnDefinition/>
17                                 <ColumnDefinition Width="1.6*"/>
18                             </Grid.ColumnDefinitions>
19                             <Grid>
20                                 <Grid.RowDefinitions>
21                                     <RowDefinition Height="40"/>
22                                     <RowDefinition/>
23                                 </Grid.RowDefinitions>
24 
25                                 <TextBlock Text="姓名" Margin="18,0" VerticalAlignment="Center"/>
26                             </Grid>
27                             <Grid Grid.Column="1">
28                                 <Grid.RowDefinitions>
29                                     <RowDefinition Height="40"/>
30                                     <RowDefinition/>
31                                 </Grid.RowDefinitions>
32 
33                                 <TextBox Grid.Row="0" Text="{Binding Name}" Height="23" VerticalContentAlignment="Center" Width="220"/>
34                                 <Button Grid.Row="6" Content="保存"  Width="88" Height="28" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="10"
35                                 CommandParameter="{Binding .,RelativeSource={RelativeSource AncestorType=Window}}" Background="LightBlue" Command="{Binding SaveCommand}" />
36                             </Grid>
37                         </Grid>
38                     </TabItem>
39                 </TabControl>
40             </Grid>
41         </Border>
42     </Grid>
43 </Window>

3、定义一下MVVM中使用的命令对象CommandBase类

复制代码
 1     public class CommandBase : ICommand
 2     {
 3         public event EventHandler CanExecuteChanged;
 4 
 5         public bool CanExecute(object parameter)
 6         {
 7             return true;
 8         }
 9 
10         public void Execute(object parameter)
11         {
12             DoExecute?.Invoke(parameter);
13         }
14 
15         public Action<object> DoExecute { get; set; }
16     }

4、创建一个用于DataGrid显示的数据模型Student,数据模型的字段名要跟DataGrid的列名绑定的属性名对应。

复制代码
 1  public class Student : INotifyPropertyChanged
 2  {
 3      public event PropertyChangedEventHandler PropertyChanged;
 4 
 5      public void NotifyChanged([CallerMemberName] string propName = "")
 6      {
 7          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));//全局通知(给监听此属性的控件)
 8      }
 9 
10      private int id;
11      private string name;
12 
13      public int ID 
14      {
15          get => id; 
16          set
17          {
18              id = value;
19              NotifyChanged();
20          }
21      }
22 
23      public string Name
24      { 
25          get => name;
26          set
27          {
28              name = value;
29              NotifyChanged();
30          }
31      }
32 
33      private CommandBase editCommand;
34 
35      public CommandBase EditCommand
36      {
37          get
38          {
39              if (editCommand == null)
40              {
41                  editCommand = new CommandBase();
42                  editCommand.DoExecute = new Action<object>(obj => {
43                     //预留
44                  });
45              }
46              return editCommand;
47          }
48 
49      }

5、为界面创建ViewModel,ViewModel里增加一个用于显示到DataGrid的列表属性StudentCollection

复制代码
 1 public class MainWindowViewModel : INotifyPropertyChanged
 2 {
 3     public event PropertyChangedEventHandler PropertyChanged;
 4 
 5     public void RaiseChanged([CallerMemberName] string propertyName = "")
 6     {
 7         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
 8     }
 9 
10     private ObservableCollection<Student> studentCollection = new ObservableCollection<Student>();
11 
12     public ObservableCollection<Student> StudentCollection
13     {
14         get => this.studentCollection;
15         set
16         {
17             studentCollection = value;
18             this.RaiseChanged();
19         }
20     }
21 }

6、构造一个测试数据,并将ViewModel绑定到主窗口的DataContext上。

复制代码
 1 public partial class MainWindow : Window
 2 {
 3     public MainWindow()
 4     {
 5         InitializeComponent();
 6 
 7         var mainviewmodel = new MainWindowViewModel();
 8 
 9         mainviewmodel.StudentCollection.Add(new Model.Student() { ID = 1, Name = "标签111111" });
10         mainviewmodel.StudentCollection.Add(new Model.Student() { ID = 2, Name = "标签222222" });
11 
12 
13         this.DataContext = mainviewmodel;
14     }
15 }

7、运行,可以看到界面显示如下:

8、增加编辑功能

需要为编辑界面增加一个ViewModel,在这个ViewModel中定义显示在界面上的字段,并增加一个保存命令

复制代码
 1 public class DataEditViewModel : INotifyPropertyChanged
 2 {
 3     public event PropertyChangedEventHandler PropertyChanged;
 4 
 5     public void RaiseChanged([CallerMemberName] string propName = "")
 6     {
 7         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
 8     }
 9 
10     private int id;
11     private string name;
12 
13     public int Num
14     {
15         get => id;
16         set
17         {
18             id = value;
19             RaiseChanged();
20         }
21     }
22 
23     public string Name
24     {
25         get => name;
26         set
27         {
28             name = value;
29             RaiseChanged();
30         }
31     }
32 
33     private CommandBase saveCommand;
34     public CommandBase SaveCommand
35     {
36         get
37         {
38             if (saveCommand == null)
39             {
40                 saveCommand = new CommandBase();
41                 saveCommand.DoExecute = new Action<object>(obj => {
42                     var window = obj as Window;
43 
44                     if (window != null)
45                         window.DialogResult = true;
46                 });
47             }
48 
49             return saveCommand;
50         }
51     }
52 }

9、回到前面定义的Student类,将EditCommand补全

因为一个数据对象就是表格的一行,所以这个编辑命令需要定义在实体类中。

复制代码
 1  public CommandBase EditCommand
 2  {
 3      get
 4      {
 5          if (editCommand == null)
 6          {
 7              editCommand = new CommandBase();
 8              editCommand.DoExecute = new Action<object>(obj => {
 9                  var connectData = obj as Student;
10                  DataEditView dataEditView = new DataEditView();
11                  DataEditViewModel dataEditViewModel = new DataEditViewModel();
12                  dataEditViewModel.Num = connectData.ID;
13                  dataEditViewModel.Name = connectData.Name;
14                  dataEditView.DataContext = dataEditViewModel;
15 
16                  if(dataEditView.ShowDialog() == true)
17                  {
18                      connectData.ID = dataEditViewModel.Num;
19                      connectData.Name = dataEditViewModel.Name;
20                  }
21              });
22          }
23          return editCommand;
24      }
25 
26  }

10、单击编辑链接,就可以弹出 一个新窗口进行编辑,编辑完成后,数据会更新到DataGrid中去。

示例代码

相关推荐
cl°12 小时前
【WPF】如何使用异步方法
经验分享·c#·wpf
月落.13 小时前
WPF的行为(Behavior)
wpf
cl°16 小时前
WPF中视觉树和逻辑树的区别和联系
经验分享·学习·c#·wpf
Nita.4 天前
WPF拖拽交互全攻略及实现自定义拖拽控件及数据交换技巧解析
c#·.net·wpf·1024程序员节
凌霜残雪4 天前
WPF+Mvvm案例实战(五)- 自定义雷达图实现
wpf
月落.4 天前
C#WPF的App.xaml启动第一个窗体的3种方式
ui·c#·wpf
月落.4 天前
WPF样式
开发语言·wpf
时光追逐者4 天前
一个基于.NET8+WPF开源的简单的工作流系统
开发语言·microsoft·c#·asp.net·.net·wpf·.netcore
界面开发小八哥4 天前
DevExpress WPF v24.1新版亮点:PDF查看器、富文本编辑器功能升级
.net·wpf·界面控件·devexpress·ui开发
就是有点傻5 天前
WPF中的Binding
大数据·wpf