I was recently working on a requirement to perform Update and Delete operations on a WPF DataGrid control (similar to what developers do in a ASP.NET Grid control). The WPF DataGrid is an excellent control to bind with collections and provides various events to work with.
In this article, I have developed a small application using ADO.NET EF (Entity Framework) and WPF DataGrid. The script for creating the Database table is in the db.sql file in the source code of this article.
Creating ADO.NET EF and WPF Project
Step 1: Open VS2010 and create a WPF project and name it as ‘WPF_DataGridEvents’.
Step 2: To this project, add a new ADO.NET Entity Model. Name it as ‘CompanyEDMX’. From the wizard for ADO.NET EF, select ‘Employee’ table created in SQL Server using the db.sql script. After the completion of the wizard, the following model will be generated:
Working with the WPF DataGrid Control
Step 1: In the MainWindow_DataGrid_Operations.xaml, drag and drop a TextBlock and DataGrid. Define columns for the DataGrid for every corresponding column name of the Entity model, as shown below:
<Window x:Class="WPF_DaatGridEvents.MainWindow_DataGrid_Operations"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow_DataGrid_Operations" Height="447" Width="909"
Loaded="Window_Loaded">
<Grid>
<DataGrid AutoGenerateColumns="False" Height="226"
HorizontalAlignment="Left" Margin="106,111,0,0"
Name="dgEmp" VerticalAlignment="Top" Width="684" ColumnWidth="*"
RowEditEnding="dgEmp_RowEditEnding" CellEditEnding="dgEmp_CellEditEnding"
SelectionChanged="dgEmp_SelectionChanged" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding EmpNo}" Header="EmpNo"
IsReadOnly="True" x:Name="dgrEmpNo">
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding EmpName}" Header="EmpName"
IsReadOnly="True" x:Name="dgrEmpName">
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Salary, Mode=TwoWay}"
Header="Salary" x:Name="dgrSalary" IsReadOnly="True">
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding DeptNo, Mode=TwoWay}"
Header="DeptNo" x:Name="dgrDeptNo" IsReadOnly="True">
</DataGridTextColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Update" x:Name="btnUpdate"
Click="btnUpdate_Click"></Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Delete" x:Name="btnDelete"
Click="btnDelete_Click"></Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<TextBlock Height="55" HorizontalAlignment="Left" Margin="106,29,0,0"
Name="textBlock1" VerticalAlignment="Top" Width="693"
Text="WPF DataGrid for Update and Delete Operations"
TextAlignment="Center" FontFamily="Verdana" FontSize="28" />
</Grid>
</Window>
In the above XAML, using the DataGridTemplateColumn, Update and Delete buttons are added. The following DataGrid Events are used:
· SelectionChanged
o This event is raised when any row from the DataGrid is selected. This returns an object of the binding source to the DataGrid.
· CellEditEnding
o This event is raised when any cell from the selected row is changed and the control is moved out of it.
· RowEditEnding
o This event is raised when after editing all cells in the row, the focus from the row is changed.
Step 2: In the Mainwindow.Xaml.cs/vb Windows loaded event, write the following code. This code will create an instance of the Entity Model and the data will be displayed in DataGrid:
C#
private void Window_Loaded(object sender, RoutedEventArgs e)
{
objContext = new CompanyEntities();
dgEmp.ItemsSource = objContext.Employee;
}
VB.NET
Private Sub Window_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
objContext = New CompanyEntities()
dgEmp.ItemsSource = objContext.Employee
End Sub
Step 3: In the ‘SelectionChanged’ event of the DataGrid, write the following code.
C#
private void dgEmp_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
objEmpToEdit = dgEmp.SelectedItem as Employee;
}
VB.NET
Private Sub dgEmp_SelectionChanged(ByVal sender As Object, ByVal e As SelectionChangedEventArgs)
objEmpToEdit = TryCast(dgEmp.SelectedItem, Employee)
End Sub
This will return an index of the Employee entity object.
Step 4: In the XAML, the DataGrid columns are made read only using ‘IsReadOnly’ property set to false. Now since Salary and DeptNo can be updated, on the click event of the ‘Update’ button, the following code is written. This code changes the columns for ‘Salary’ and ‘DeptNo’ in edit mode.
C#
private void btnUpdate_Click(object sender, RoutedEventArgs e)
{
isUpdateMode = true;
dgEmp.Columns[2].IsReadOnly = false;
dgEmp.Columns[3].IsReadOnly = false;
}
VB.NET
Private Sub btnUpdate_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
isUpdateMode = True
dgEmp.Columns(2).IsReadOnly = False
dgEmp.Columns(3).IsReadOnly = False
End Sub
Performing Update Operation in the WPF DataGrid
Step 5: Write the following code in the ‘CellEditEnding’ event
C#
private void dgEmp_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (isUpdateMode) //The Row is edited
{
Employee TempEmp = (from emp in objContext.Employee
where emp.EmpNo == objEmpToEdit.EmpNo
select emp).First();
FrameworkElement element_1 = dgEmp.Columns[2].GetCellContent(e.Row);
if (element_1.GetType() == typeof(TextBox))
{
var xxSalary = ((TextBox)element_1).Text;
objEmpToEdit.Salary = Convert.ToInt32(xxSalary);
}
FrameworkElement element_2 = dgEmp.Columns[3].GetCellContent(e.Row);
if (element_2.GetType() == typeof(TextBox))
{
var yyDeptNo = ((TextBox)element_2).Text;
objEmpToEdit.DeptNo = Convert.ToInt32(yyDeptNo);
}
}
}
VB.NET
Private Sub dgEmp_CellEditEnding(ByVal sender As Object, ByVal e As DataGridCellEditEndingEventArgs)
If isUpdateMode Then 'The Row is edited
Dim TempEmp As Employee = (
From emp In objContext.Employee
Where emp.EmpNo = objEmpToEdit.EmpNo
Select emp).First()
Dim element_1 As FrameworkElement = dgEmp.Columns(2).GetCellContent(e.Row)
If element_1.GetType() Is GetType(TextBox) Then
Dim xxSalary = (CType(element_1, TextBox)).Text
objEmpToEdit.Salary = Convert.ToInt32(xxSalary)
End If
Dim element_2 As FrameworkElement = dgEmp.Columns(3).GetCellContent(e.Row)
If element_2.GetType() Is GetType(TextBox) Then
Dim yyDeptNo = (CType(element_2, TextBox)).Text
objEmpToEdit.DeptNo = Convert.ToInt32(yyDeptNo)
End If
End If
End Sub
This code first searches the selected Employee row using LINQ. After the row is found, the update operation is performed on it. In DataGrid, every Cell is in the form of TextBlock FrameworkElement type when it is not editable. So to read the edited cell value, you need to read the Cell contents using ‘GetCellContent()’ method, by passing the DataGridRow object to it. Once the FrameworkElement is extracted, by type casting it to the ‘TextBox’ UI element, the value changed in the cell can be read. Here ‘Salary’ and ‘DeptNo’ are changed and updated into the selected ‘Employee’ object.
Step 6: To update changes back to the Database using Entity Model, the ‘RowEditEnding’ event is implemented as shown below:
C#
private void dgEmp_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
objContext.SaveChanges();
MessageBox.Show("The Current row updation is complete..");
}
VB.NET
Private Sub dgEmp_RowEditEnding(ByVal sender As Object, ByVal e As DataGridRowEditEndingEventArgs)
objContext.SaveChanges()
MessageBox.Show("The Current row updation is complete..")
End Sub
Performing Delete operation in WPF DataGrid
Step 7: For performing the Delete operation, the following code is written on the click event of the ‘Delete’ button.
C#
private void btnDelete_Click(object sender, RoutedEventArgs e)
{
if (objEmpToEdit == null)
{
MessageBox.Show("Cannot delete the blank Entry");
}
else
{
objContext.DeleteObject(objEmpToEdit);
objContext.SaveChanges();
MessageBox.Show("Record Deleted..");
}
}
VB.NET
Private Sub btnDelete_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
If objEmpToEdit Is Nothing Then
MessageBox.Show("Cannot delete the blank Entry")
Else
objContext.DeleteObject(objEmpToEdit)
objContext.SaveChanges()
MessageBox.Show("Record Deleted..")
End If
End Sub
The Template column generates buttons for all rows, which will add buttons for the last row where no data is present. So the ‘if’ statement in the above code, will prevent the application from crashing, since the WPF DataGrid generates a blank row when the data is bound to it. When the delete button is clicked, the row will be deleted from the database.
Step 8: Now run the application, click on the update button in the row and select cell to be changed (in this example ‘Salary’ and ‘DeptNo’ cells can be changed). After changing cell or cells for the row, use ‘TAB’ on your keyboard to change the focus from the current row to next row. This will fire the ‘RowEditEnding’ event and the update will be completed.
Similarly you can click on the Delete button on the specific row and the row will be deleted from the databsse.
Changing the DeptNo, (after using ‘TAB’) the following result will be displayed:
As you can see above, the DeptNo 50 has been changed to 60.
Click on the Delete on the row for EmpNo = 106 and the following result will be displayed:
As you saw, we are now able to perform Update and Delete operations on the WPF DataGrid control. The entire source code of this article can be downloaded over here
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Mahesh Sabnis is a DotNetCurry author and a Microsoft MVP having over two decades of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions), and Front-end technologies like Angular and React. Follow him on twitter @
maheshdotnet or connect with him on
LinkedIn