Reputation: 1
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>
<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
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
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
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