
This article deals with the GridView WebForms .NET control; in particular with how to detect and record changes after the user has saved data in the GridView.
Sometimes using WebForms controls is not well documented and unintuitive, which is the case with the onRowUpdated event, where a lot of information available online is incorrect or misleading. I hope my findings in this article help you. If they do (or if they don’t), then please leave a comment.
By the way, if you find the information I’m giving is useful, then have a look at some of the other WebForms related articles I’ve written.
So What’s the Question?
At this time in 2017, the WebForms technology is not as commonly used as it once was, but is still relatively prevalent, especially in legacy applications.
You may be asking yourself: what’s the question here? Well, if you’ve got a GridView, you may want to have programmatic decision making logic in place based on an update event happening. This might be useful if you are checking to see if the user actually changed a value, or just clicked the update button.
In this case you have the option of catching the update event before the database update happens (onRowUpdating) or after the database update has happened (onRowUpdated).
Using onRowUpdated
As I mentioned, the onRowUpdated method is triggered after the GridView’s update event has happened. This can be a useful opportunity to save information to a historical record. For example, maybe you want to check if the has user actually changed anything before you save the before and after information to a historical table. In this case, you can use the onRowUpdated method to check before and after values for the field you are interested in.
In the example code at the end of this article, notice that I’m checking the state of an imaginary field called ‘Status’. Contrary to some claims, I’ve not yet found an automatic way that you can detect the before and after state of a field in the onRowUpdated method. This is likely because this event takes place after the database Save has taken place.
To achieve the desired before/after detection behavior, I’ve added a hidden read-only data field in the GridView markup that will hold the original value of the field. That way on the onRowUpdated method we have to grab the row that was updated, and then manually compare the state of the user-available ‘Status’ dropdown list with the value in the read-only field.
Getting the Updated Row: Step #1
So how can we go about getting the row that was updated? Again, this is not as easy a task as one might imagine. Luckily in the GridViewUpdatedEventArgs we can get the updated row’s DataKeyNames (which in this case is ‘Id’). Here’s the code to get the Id:
In VB.NET:
Dim keyFieldValue As String = e.Keys("Id").ToString()
In C#:
string keyFieldValue = e.Keys("Id").ToString();
Getting the Updated Row: Step #2
There’s now no other way to get the edited row number other than looping through the rows of the GridView and comparing the datakey value of each row with the key that was passed to the onRowUpdated method from the GridViewUpdatedEventArgs parameter.
Here is how you do the loop and comparison in VB.NET
For Each tmpRow As GridViewRow In myGridE.Rows Dim tmpKey As String = myGridE.DataKeys(tmpRow.RowIndex).Value.ToString() If tmpKey.Equals(keyFieldValue) Then
And here’s how you do the loop and comparison in C#:
foreach (GridViewRow tmpRow in myGridE.Rows) {
string tmpKey = myGridE.DataKeys(tmpRow.RowIndex).Value.ToString();
if (tmpKey.Equals(keyFieldValue)) {
Putting the Example Together
Now that we’ve stepped through the details, let’s look at the MarkUp for the GridView as well as the methods (in VB.NET and C#) to find the edited grid like and run our custom code.
Here’s Partial MarkUp for the Interesting Parts of the GridView:
<asp:GridView ID="gvTestGridE" runat="server" DataSourceId="SqlDSTestGrid" AutoGenerateColumns="false" CellPadding="0" CellSpacing="0" BorderWidth="0px" RowStyle-BorderWidth="0" AlternatingRowStyle-BorderWidth="0" GridLines="None" ShowHeader="true" EditIndex="-1" AllowSorting="False" ShowHeaderWhenEmpty="True" AllowPaging="True" PageSize="20" DataKeyNames="Id" HeaderStyle-BackColor="#5A8FBA" HeaderStyle-ForeColor="White" AlternatingRowStyle-BackColor="#EEF5FD" Width="1150" HeaderStyle-Height="20px" OnRowUpdated="TestUpdated" > <RowStyle Font-Size="10pt" /> <Columns> <asp:TemplateField HeaderText="Status" HeaderStyle-Font-Size="12px" HeaderStyle-Width="180" HeaderStyle-HorizontalAlign="Left"> <EditItemTemplate> <asp:DropDownList ID="ddlStatus_E" runat="server" DataSourceId="SQLDsStatus" DataTextField="Status" DataValueField="Status" selectedvalue='<%# Bind("Status") %>'> </asp:DropDownList> <asp:Label ID="lblStatus_Original" runat="server" Text='<%# Eval("Status") %>' CssClass="hiddenDataField"></asp:Label> </EditItemTemplate>
Here’s the Example Method in VB.NET:
Protected Overridable Sub TestUpdated(sender As Object, e As GridViewUpdatedEventArgs) Dim intEditedRowNum As Int32 = 0 Dim keyFieldValue As String = e.Keys("Id").ToString() Dim myGridE As GridView = CType(sender, GridView) Dim lblTest As Label = Page.FindControl("lbltestresults") For Each tmpRow As GridViewRow In myGridE.Rows Dim tmpKey As String = myGridE.DataKeys(tmpRow.RowIndex).Value.ToString() If tmpKey.Equals(keyFieldValue) Then intEditedRowNum = tmpRow.RowIndex Dim strOriginalDdlValue As String = CType(tmpRow.FindControl("lblStatus_Original"), Label).Text Dim strUserSelectedDdlValue As String = CType(tmpRow.FindControl("ddlStatus_E"), DropDownList).SelectedValue lblTest.Text = strOriginalDdlValue & " - " & strUserSelectedDdlValue End If Next End Sub
Here’s the Same Example Method in C#:
protected virtual void BillingUpdated(object sender, GridViewUpdatedEventArgs e) { Int32 intEditedRowNum = 0; string keyFieldValue = e.Keys("Id").ToString(); GridView myGridE = (GridView)sender; Label lblTest = Page.FindControl("lbltestresults"); foreach (GridViewRow tmpRow in myGridE.Rows) { string tmpKey = myGridE.DataKeys(tmpRow.RowIndex).Value.ToString(); if (tmpKey.Equals(keyFieldValue)) { intEditedRowNum = tmpRow.RowIndex; string strOriginalDdlValue = ((Label)tmpRow.FindControl("lblStatusEdt_Original")).Text; string strUserSelectedDdlValue = ((DropDownList)tmpRow.FindControl("ddlStatusEdt_E")).SelectedValue; lblTest.Text = strOriginalDdlValue + " - " + strUserSelectedDdlValue; } } }