当前位置: 首页 > article >正文

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中去。

示例代码


http://www.kler.cn/news/363890.html

相关文章:

  • npm install 安装很慢怎么办?
  • 提示词高级阶段学习day2.2
  • 使用 CDN 后 Apache 的日志记录客户真实 IP
  • 工作使用的工具
  • 算法Day-9
  • Ivanti云服务被攻击事件深度解析:安全策略构建与未来反思
  • vue2.x 的依赖收集通知更新
  • 【力扣 | SQL题 | 每日4题】力扣1164,3293,1308,1270
  • 【scene_manager_msgs】ROS2 自定义消息、服务的包
  • 动态规划:17.简单多状态 dp 问题_买卖股票的最佳时机III_C++
  • OpenCV高级图形用户界面(17)设置一个已经创建的滚动条的最小值函数setTrackbarMin()的使用
  • 七、高级查询和数据操作及数据完整性和约束
  • 基于Linux来讲解Kconfig的基础知识
  • 【2024版】sql-liabs靶场前十关解题过程和思路----适合入门小白
  • Appium环境搭建全流程(含软件)
  • Java项目-基于springboot框架的社区疫情防控平台系统项目实战(附源码+文档)
  • React 纯手写一个 Modal 组件,除了样式不太美观以外,其他功能都不错呢?附上全部源码
  • vscode ssh连接远程服务器一直卡在正在打开远程
  • linux,socket编程,select,poll,epoll学习
  • MATLAB基础应用精讲-【数模应用】负二项回归(附R语言和python代码实现)
  • OpenCV高级图形用户界面(16)设置一个已经创建的滚动条的最大值函数setTrackbarMax()的使用
  • 【跑酷项目02】实现触发并在前方克隆金币
  • 编辑器加载与AB包加载组合
  • SQL注入原理、类型、危害与防御
  • 使用cmdline-tools安装Android SDK与NDK
  • 驱动开发系列20 - Linux Graphics Xorg-server 介绍