Sherif
Sherif

Reputation: 1

ASP.Net: Gridview throws error 'fired event RowUpdating which wasn't handled'

I have a Gridview on an ASP page bound to an SQL table. I've configured the Grid to allow Multiple updates by replacing the default Label Controls with TemplateFields using the approach described here: Bulk Updates to Rows Bound to a GridView

Everything was working fine, until I made a change to bind the Gridview query programmatically on page load (With the aim of making the Gridview display different data depending on the user currently viewing the page) as described here: Bind Gridview programmatically. After making this change the page now throws the following error when the user makes changes and clicks the update button:

The GridView 'GridView1' fired event RowUpdating which wasn't handled.

Also when I try to do a single row update I get this error:

Exception Details: System.Web.HttpException: The GridView 'GridView1' fired event RowEditing which wasn't handled.

I have read many threads on similair problems but I can't seem to find a solution to my error. I don't know why dynamically binding the Gridview would cause an error in rowupdating. Appreciate any support to resolve this. Thanks.

Here's the Code:

Public Class Input
Inherits System.Web.UI.Page

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If Not IsPostBack Then

        gvbind()


    End If



End Sub

Public Sub gvbind()

    Dim SqlDataSource1 As New SqlDataSource()
    SqlDataSource1.ID = "SqlDataSource1"
    Me.Page.Controls.Add(SqlDataSource1)
    SqlDataSource1.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString

    SqlDataSource1.SelectCommand = "SELECT [ID], [Project], [Description], [CAPEX], [Team] FROM [CAPEX]"
    'Add Conditional Statements to change view for users/Teams
    'SqlDataSource1.SelectCommand = "SELECT [ID], [Project], [Description], [CAPEX] FROM [CAPEX] where [Team] = 'Team1'"

    GridView1.DataSource = SqlDataSource1
    GridView1.DataBind()

End Sub


Private tableCopied As Boolean = False
Private originalDataTable As System.Data.DataTable

Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
    If e.Row.RowType = DataControlRowType.DataRow Then
        If Not tableCopied Then
            originalDataTable = CType(e.Row.DataItem, System.Data.DataRowView).Row.Table.Copy()
            ViewState("originalValuesDataTable") = originalDataTable
            tableCopied = True
        End If
    End If
End Sub

Protected Sub Up_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Up.Click
    originalDataTable = CType(ViewState("originalValuesDataTable"), System.Data.DataTable)

    For Each r As GridViewRow In GridView1.Rows
        If IsRowModified(r) Then GridView1.UpdateRow(r.RowIndex, False)
    Next

    ' Rebind the Grid to repopulate the original values table.
    tableCopied = False
    GridView1.DataBind()

End Sub



Protected Function IsRowModified(ByVal r As GridViewRow) As Boolean
    Dim currentID As Integer
    Dim currentProject As String
    Dim currentDescription As String
    Dim currentCAPEX As String

    currentID = Convert.ToInt32(GridView1.DataKeys(r.RowIndex).Value)

    currentProject = CType(r.FindControl("ProjectTextBox"), TextBox).Text
    currentDescription = CType(r.FindControl("DescriptionTextBox"), TextBox).Text
    currentCAPEX = CType(r.FindControl("CAPEXTextBox"), TextBox).Text

    Dim row As System.Data.DataRow = _
        originalDataTable.Select(String.Format("ID = {0}", currentID))(0)

    If Not currentProject.Equals(row("Project").ToString()) Then Return True
    If Not currentDescription.Equals(row("Description").ToString()) Then Return True
    If Not currentCAPEX.Equals(row("CAPEX").ToString()) Then Return True
    Return False
End Function

Here's the Markup:

    <%@ Page Title="Input" Language="vb" MasterPageFile="~/Site.Master" AutoEventWireup="false"
CodeBehind="Input.aspx.vb" Inherits="WebApplication5.Input" %>

<asp:Content ID="HeaderContent" runat="server"  ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server"   ContentPlaceHolderID="MainContent">
<h2>
    Data Entry
</h2>
<p>
    Enter Inputs Here<asp:TextBox runat="server" Text='<%# Bind ("Project") %>' 
        id="TextBox4"></asp:TextBox>
&nbsp;<asp:Table ID="Entry" runat="server">
    </asp:Table>
    <asp:Button ID="TestButton" runat="server" Text="Test" />
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
       AllowSorting="True" AllowPaging="True" datakeynames = "ID" Width="502px">

        <Columns>
            <asp:CommandField ShowEditButton="True" />
            <asp:BoundField DataField="ID" readOnly = "true" HeaderText="ID" SortExpression="ID"/>
            <asp:TemplateField HeaderText="Project" SortExpression="Project">
                <EditItemTemplate>
                    <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("Project") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:TextBox ID="ProjectTextBox" runat="server" MaxLength="30" 
                        Text='<%# Bind("Project") %>'></asp:TextBox>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Description" SortExpression="Description">
                <EditItemTemplate>
                    <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("Description") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:TextBox ID="DescriptionTextBox" runat="server" MaxLength="150" 
                        Text='<%# Bind("Description") %>'></asp:TextBox>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="CAPEX" SortExpression="CAPEX">
                <EditItemTemplate>
                    <asp:TextBox ID="TextBox3" runat="server" Text='<%# Bind("CAPEX") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:TextBox ID="CAPEXTextBox" runat="server" MaxLength="10" 
                        Text='<%# Bind("CAPEX") %>'></asp:TextBox>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>


    <asp:SqlDataSource ID="SqlDataSource2" runat="server" 
        ConnectionString="<%$ ConnectionStrings:ConnectionString %>" 

        SelectCommand="SELECT [ID], [Project], [Description], [CAPEX] FROM [CAPEX]" 
        DeleteCommand="DELETE FROM [CAPEX] WHERE [ID] = @ID" 
        InsertCommand="INSERT INTO [CAPEX] ([ID], [Project], [Description], [CAPEX], [Team]) VALUES (@ID, @Project, @Description, @CAPEX, @Team)" 
        UpdateCommand="UPDATE [CAPEX] SET [Project] = @Project, [Description] = @Description, [CAPEX] = @CAPEX,[Team] = @Team WHERE [ID] = @ID">
        <DeleteParameters>
            <asp:Parameter Name="ID" Type="String" />
        </DeleteParameters>
        <InsertParameters>
            <asp:Parameter Name="ID" Type="String" />
            <asp:Parameter Name="Project" Type="String" />
            <asp:Parameter Name="Description" Type="String" />
            <asp:Parameter Name="CAPEX" Type="Decimal" />
        </InsertParameters>
        <UpdateParameters>
            <asp:Parameter Name="Project" Type="String" />
            <asp:Parameter Name="Description" Type="String" />
            <asp:Parameter Name="CAPEX" Type="Decimal" />
            <asp:Parameter Name="ID" Type="String" />
            <asp:Parameter Name="Team" Type="String" />
        </UpdateParameters>
    </asp:SqlDataSource>
    <asp:Button ID="Up" runat="server" Text="Up" />
    <asp:SqlDataSource ID="SqlDataSource1" runat="server"></asp:SqlDataSource>
    <asp:Table ID="Table1" runat="server" BorderWidth="1" BorderStyle="Solid">
    </asp:Table>
</p>

Upvotes: 0

Views: 3430

Answers (3)

xavigonza
xavigonza

Reputation: 170

I see that SqlDataSource1 definition in codebehind lacks the UpdateCommand definition. To be honest I always used the SqlDataSource2 approach, it'd be as easy as add DataSourceID="SqlDataSource2" and the markup would be:

   <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
   AllowSorting="True" AllowPaging="True" DataKeyNames = "ID"
   DataSourceID="SqlDataSource2" Width="502px">

That way you can forget about if the gridview has to be bound in postbacks. Unless you place the gridview inside an UpdatePanel, I'd say it has to be bound, and then the If Not IsPostBack Then is incorrectly placed.

The code <asp:TextBox runat="server" Text='<%# Bind ("Project") %>' id="TextBox4"></asp:TextBox> looks placed outside of a databound control.

Upvotes: 0

j.f.
j.f.

Reputation: 3949

Adding to fnostro's answer about GridView1.UpdateRow() raising RowUpdated and RowUpdating, showing the edit button like you do:

<asp:CommandField ShowEditButton="True" />

will generate a button with CommandName="Edit". Clicking this button will raise the RowEditing event, which you also need to handle in your code.

And as a side note, since your "Update" button is outside your GridView, the CommandName property won't be responsible for automatically firing a GridView event. So not only will changing the ID from "Update" to "Up" not have any affect, but changing the CommandName wouldn't have either.

Upvotes: 0

fnostro
fnostro

Reputation: 4591

You make a call in Up_Click to 'GridView1.UpdateRow()'

From the MSDN Docs:

Calling this method also raises the RowUpdated and RowUpdating events.

So all you should need to do is provide empty handlers

Upvotes: 1

Related Questions