WPF DataGrid Control - Performing Update and Delete Operations

Posted by: Mahesh Sabnis , on 8/27/2010, in Category WPF
Views: 140555
Abstract: 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.
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.
Note: If you are new to creating applications using WPF and ADO.NET EF then read my previous article Creating Applications using Windows Presentation Foundation (WPF) Commanding and ADO.NET Entity Framework
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:
Employee
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.
DataGrid
Changing the DeptNo, (after using ‘TAB’) the following result will be displayed:
REcordUpdation
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:
REcordDeletion
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
Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles
Mahesh is having 10 years 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). Follow him on twitter @maheshdotnet


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by John Lundy on Tuesday, December 21, 2010 12:56 AM
Mahesh is it possible to change this so that you don't have the update button and you can fire the update event when leaving a row, the same as an access application works?
Comment posted by John Lundy on Tuesday, December 21, 2010 1:10 AM
There seems to be no db.sql in the source code
Comment posted by Mahesh Sabnis on Tuesday, December 28, 2010 5:21 AM
Hi John Lundy,

  You can do that.The RowEditEnding event is used for the Update operation. When this event is completed make call to Update Method form the DAL and pass the object associated (EMployee) with the selected row. No need to use Update button then in that case.
Thanks
Regards
MAhesh Sabnis
Comment posted by Kanwal Shehzad on Monday, February 28, 2011 4:30 AM
Dear Mahesh,
Thanks for your helpful article. I am working WPF4, and have bounded DataGrid with list of entities. I have problems in editing & insertion.
I need that when any row is in edit mode or has generated validations error, it should not leave focus.
How can i distinguish that user has finished editing. I tried to use DataGridEditAction but still same problems.

Can you please do me a favor and help me out by giving some sample code.

Regards,
Comment posted by EDUARDO RAMIREZ on Saturday, May 21, 2011 2:52 PM
hi Mahesh , i have a problem with a datagrid control in wpf.

My datagrid have 2 columns with datacontext (LINQ) and 2 columns for users put adicional information. i need take all value for datagrid and then save in database. How i do that?

    <my:DataGrid Grid.ColumnSpan="4" Grid.Row="4" Grid.RowSpan="9" Height="297" HorizontalAlignment="Left" Margin="17,2,0,0" Name="dg_recaudos" VerticalAlignment="Top" Width="878" AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="Cell">
                <my:DataGrid.Columns>
                    <my:DataGridCheckBoxColumn CanUserReorder="False" CanUserResize="False" CanUserSort="False" Width="60" />
                    <my:DataGridTextColumn Header="" Binding="{Binding ID_DOCUMENTO, Mode=OneWay}" Width="auto" CanUserReorder="False" CanUserSort="False" Visibility="Hidden"/>
                    <my:DataGridTextColumn Header="Documento / Recaudo" Binding="{Binding DOCUMENTO, Mode=OneWay}" Width="600" CanUserReorder="False" CanUserSort="False" CanUserResize="False" >
                        <my:DataGridTextColumn.ElementStyle>
                            <Style TargetType="TextBlock">
                                <Setter Property="TextWrapping" Value="Wrap" />
                            </Style>
                        </my:DataGridTextColumn.ElementStyle>
                    </my:DataGridTextColumn>
                    <my:DataGridTemplateColumn Header="Observación" CanUserReorder="False" CanUserSort="False" Width="200">
                        <my:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBox Text=""/>
                            </DataTemplate>
                         </my:DataGridTemplateColumn.CellTemplate>
                        <!--<my:DataGridTemplateColumn.CellEditingTemplate>
                            <DataTemplate>
                                <TextBlock Text=""/>
                            </DataTemplate>
                        </my:DataGridTemplateColumn.CellEditingTemplate>-->

                    </my:DataGridTemplateColumn>
                </my:DataGrid.Columns>
            </my:DataGrid>

Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnOK.Click
        Dim filas As Integer = dg_recaudos.Items.Count
        Dim entregado As Char = ""
        Dim i As Integer = 0
        Dim col As Integer = 0
        Dim valor As String
        Dim row As DataGridRow

        For i = 0 To (filas - 1)
            col = dg_recaudos.Columns.Count

            Dim element_1 As FrameworkElement = dg_recaudos.Columns(2).GetCellContent(i)


        Next
    End Sub

THANKS

SORRY FOR MY ENGLISH
Comment posted by Kunwar Deep on Tuesday, March 13, 2012 9:46 AM
Check this helpful links too its also having nice post with wonderful explanation on WPF DataGrid Control...
http://www.c-sharpcorner.com/Blogs/7958/datagrid-control-in-wpf.aspx
http://mindstick.com/Articles/5f9c899a-b566-4b81-b84e-36aec3547342/?DataGrid%20control%20in%20WPF

Comment posted by avi on Saturday, July 21, 2012 7:33 AM
To read the edited cell value, you need to read the Cell contents using ‘GetCellContent()’ method, by passing the DataGridRow object to it.
http://www.dapfor.com
Comment posted by sumit k gupta on Monday, May 27, 2013 4:47 AM
Hello Mahesh.

I am new to WPF. I want to know that if i put single update button after the grid.  And i want that edited rows should be updated on click of this update button.

Thanks

Sumit K Gupta
Comment posted by Bhavin on Saturday, September 7, 2013 1:32 AM
Please Give one demo.
this code is write but some file not understand please help me.
Comment posted by arun on Tuesday, October 1, 2013 7:19 AM
Employee TempEmp = (from emp in objContext.Employee
                            where emp.EmpNo == objEmpToEdit.EmpNo
                            select emp).First();
_________________________________________________________________________
what is the functionality of above code in the update operation
without this also it functions well
Comment posted by Arijit on Monday, June 16, 2014 2:17 AM
Hi Mahesh,

The Source COde Link is not working.

Thanks,

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel