前言
在WPF开发中,DataGrid是一个非常常用的控件,用于展示和操作表格数据。而MVVM(Model-View-ViewModel)模式则是WPF推荐的开发架构,它将界面逻辑与业务逻辑分离,提高了代码的可维护性和可测试性。
本文将手把手带你实现一个基于MVVM模式的DataGrid编辑功能,不依赖任何第三方框架,适合初学者理解和学习。
正文
要实现DataGrid的编辑功能,我们需要创建两个窗口:一个用于显示数据,另一个用于编辑数据。以下是具体的实现步骤。
1、创建主窗口用于显示DataGrid
我们首先创建一个MainWindow,其中包含一个DataGrid控件,用于显示学生信息。
布局如下:
MainWindow.xaml
<Window x:Class="WPFDataGridEditDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFDataGridEditDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<DataGrid x:Name="datagrid" ItemsSource="{Binding StudentCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False"
CanUserAddRows="False" VerticalScrollBarVisibility="Hidden" IsReadOnly="True" Margin="20">
<DataGrid.Columns>
<DataGridTextColumn Header="学号" Width="60" Binding="{Binding ID}"/>
<DataGridTextColumn Header="姓名" Width="*" Binding="{Binding Name}"/>
<DataGridTemplateColumn Header="操作" Width="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,5,0">
<Hyperlink Command="{Binding EditCommand}" CommandParameter="{Binding ElementName=datagrid,Path=SelectedItem}">编辑</Hyperlink>
</TextBlock>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
2、创建编辑窗口
接下来,我们创建一个DataEditView窗口,用于编辑学生信息。
布局如下:
DataEditView.xaml
<Window x:Class="WPFDataGridEditDemo.Views.DataEditView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFDataGridEditDemo.Views"
mc:Ignorable="d"
Title="DataEditView" Height="450" Width="800">
<Grid>
<Border>
<Grid Background="Transparent">
<TabControl BorderThickness="0" Margin="0,5">
<TabItem Header="学生信息" FontSize="12">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="1.6*"/>
</Grid.ColumnDefinitions>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="姓名" Margin="18,0" VerticalAlignment="Center"/>
</Grid>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="{Binding Name}" Height="23" VerticalContentAlignment="Center" Width="220"/>
<Button Grid.Row="6" Content="保存" Width="88" Height="28" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="10"
CommandParameter="{Binding .,RelativeSource={RelativeSource AncestorType=Window}}" Background="LightBlue" Command="{Binding SaveCommand}" />
</Grid>
</Grid>
</TabItem>
</TabControl>
</Grid>
</Border>
</Grid>
</Window>
3、定义命令对象
为了实现命令绑定,我们需要定义一个CommandBase类,实现ICommand接口:
public class CommandBase : ICommand
{
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
DoExecute?.Invoke(parameter);
}
public Action<object> DoExecute { get; set; }
}
4、创建数据模型
创建一个Student类,实现INotifyPropertyChanged接口,以便在属性变化时通知UI更新:
public class Student : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyChanged([CallerMemberName] string propName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
private int id;
private string name;
public int ID
{
get => id;
set
{
id = value;
NotifyChanged();
}
}
public string Name
{
get => name;
set
{
name = value;
NotifyChanged();
}
}
private CommandBase editCommand;
public CommandBase EditCommand
{
get
{
if (editCommand == null)
{
editCommand = new CommandBase();
editCommand.DoExecute = new Action<object>(obj => {
//预留
});
}
return editCommand;
}
}
}
5、创建ViewModel
为MainWindow创建一个ViewModel,包含一个StudentCollection属性,用于绑定到DataGrid:
public class MainWindowViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaiseChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private ObservableCollection<Student> studentCollection = new ObservableCollection<Student>();
public ObservableCollection<Student> StudentCollection
{
get => this.studentCollection;
set
{
studentCollection = value;
this.RaiseChanged();
}
}
}
6、绑定ViewModel
在MainWindow的构造函数中,创建ViewModel实例,并添加测试数据:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var mainviewmodel = new MainWindowViewModel();
mainviewmodel.StudentCollection.Add(new Model.Student() { ID = 1, Name = "标签111111" });
mainviewmodel.StudentCollection.Add(new Model.Student() { ID = 2, Name = "标签222222" });
this.DataContext = mainviewmodel;
}
}
7、实现编辑功能
为编辑窗口创建一个ViewModel,包含保存命令:
public class DataEditViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaiseChanged([CallerMemberName] string propName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
private int id;
private string name;
public int Num
{
get => id;
set
{
id = value;
RaiseChanged();
}
}
public string Name
{
get => name;
set
{
name = value;
RaiseChanged();
}
}
private CommandBase saveCommand;
public CommandBase SaveCommand
{
get
{
if (saveCommand == null)
{
saveCommand = new CommandBase();
saveCommand.DoExecute = new Action<object>(obj => {
var window = obj as Window;
if (window != null)
window.DialogResult = true;
});
}
return saveCommand;
}
}
}
8、补全编辑命令
在Student类中补全EditCommand,实现点击"编辑"时弹出编辑窗口:
public CommandBase EditCommand
{
get
{
if (editCommand == null)
{
editCommand = new CommandBase();
editCommand.DoExecute = new Action<object>(obj => {
var connectData = obj as Student;
DataEditView dataEditView = new DataEditView();
DataEditViewModel dataEditViewModel = new DataEditViewModel();
dataEditViewModel.Num = connectData.ID;
dataEditViewModel.Name = connectData.Name;
dataEditView.DataContext = dataEditViewModel;
if(dataEditView.ShowDialog() == true)
{
connectData.ID = dataEditViewModel.Num;
connectData.Name = dataEditViewModel.Name;
}
});
}
return editCommand;
}
}
运行程序,点击"编辑"链接,即可弹出编辑窗口,修改数据后保存,数据会自动更新到DataGrid中。
总结
通过以上步骤,我们实现了基于MVVM模式的DataGrid编辑功能。整个过程不依赖任何第三方框架,代码清晰易懂,适合初学者学习和理解MVVM模式的基本原理。关键在于正确使用数据绑定、命令和通知机制,将界面逻辑与业务逻辑分离,提高代码的可维护性。
关键词
WPF、MVVM、DataGrid、编辑、命令、数据绑定、ViewModel