Monday, March 26, 2012

UpdatePanel / Gridview / ButtonField - Strange Behaviour

Hi everyone,

I have a strange problem that I've managed to narrow down to being an issue with the UpdatePanel control. Hopefully someone could advise me...

I have an UpdatePanel which contains a Gridview which isnot bound to a dataset etc. I populate the gridview manually by constructing my own table, defining grid columns then binding it to my table etc. Several of the columns in the gridview are of typeButtonField withButtonType set to "Button"

Now, all of this is working fine...no problems whatsoever.

I decided later that rather than a button I wanted a link instead, so where I construct the GridView's columns using a ButtonField column type, I simply changed
"MyCol.ButtonType = ButtonType.Button" to "MyCol.ButtonType = ButtonType.Link"

My problem is that by making this simple change, the page now does not work. The page still renders exactly as expected, but when I click on one of the link buttons, none of the events are fired...instead, I get the icon at the bottom left of explorer indicating an error on the page. When I look at the error all I get is:

Line: 1
Char: 1
Error: Object expected
Code: 0
URL: xxxxxxxxxx

Remember, the only change I made was to change the ButtonType, nothing else.

This issue seems to be related to the UpdatePanel as when I remove the Ajax controls from the page, it performs exactly as expected...that is, my code to catch the MyGrid_RowCommand event fires whether the ButtonType is Button or Link. When I put the UpdatePanel back, the page only works when ByttonType is set to Button, but not for Link.

Please note that I do not want a HyperLink field. I want a ButtonField so that I can catch the click events and process them. My Code that I'm using for testing this is below.

Thanks in advance,

MJ

To test this, try the code as-is below to replicate the error. Change the "Code-Behind" and set the ButtonType to Button and it will work. For the third test, remove the Ajax controls from the Web Page and the code will work with ButtonType set to Button or Link

HTML PAGE

<%@dotnet.itags.org. Page Language="VB" AutoEventWireup="true" CodeFile="HomePage.aspx.vb" Inherits="_HomePage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Testing</title>
</head>
<body>
<form id="form1" runat="server">
<atlas:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="True">
</atlas:ScriptManager>
<atlas:UpdatePanel ID="UpdatePanel1" runat="server" EnableViewState="true" >
<ContentTemplate>
<asp:Button ID="Button1" runat="server" Text="Button" />
<asp:GridView ID="MyGrid" runat="server" />
<asp:Label ID="lblResults" runat="server" />
</ContentTemplate>
</atlas:UpdatePanel>
</form>
</body>
</html>

CODE BEHIND


Partial Class _HomePage
Inherits System.Web.UI.Page

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click

MyGrid.DataBind()

End Sub
Protected Sub MyGrid_DataBinding(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyGrid.DataBinding

Dim MyRowPtr As Integer
Dim MyTable As New Data.DataTable

'Initialise Grid properties
With MyGrid
.AutoGenerateColumns = False
.BorderWidth = 1
.CellPadding = 0
.CellSpacing = 0
.Columns.Clear()
.EnableViewState = True
End With

'Create Table Columns
'Create Grid Columns
For MyRowPtr = 1 To 3
Dim lTableCol As New Data.DataColumn
lTableCol.ColumnName = Chr(MyRowPtr + 64)
MyTable.Columns.Add(lTableCol)

Dim lGridCol As New ButtonField
With lGridCol
.ButtonType = ButtonType.Link ' <======= CHANGE THIS LINE HERE
.ControlStyle.BorderWidth = 0
.ControlStyle.BorderStyle = BorderStyle.NotSet
.ControlStyle.BackColor = Drawing.Color.Azure
.CausesValidation = True
.HeaderText = Chr(MyRowPtr + 64)
.DataTextField = lTableCol.ColumnName
.CommandName = MyRowPtr.ToString
End With

MyGrid.Columns.Add(lGridCol)

Next

'Create 2 rows in the data table
Dim MyRow As Data.DataRow

MyRow = MyTable.NewRow
MyRow.BeginEdit()
MyRow("A") = "Row0 Col1"
MyRow("B") = "Row0 Col2"
MyRow("C") = "Row0 Col3"
MyRow.EndEdit()
MyTable.Rows.Add(MyRow)

MyRow = MyTable.NewRow
MyRow.BeginEdit()
MyRow("A") = "Row1 Col1"
MyRow("B") = "Row1 Col2"
MyRow("C") = "Row1 Col3"
MyRow.EndEdit()
MyTable.Rows.Add(MyRow)

MyTable.AcceptChanges()

MyGrid.DataSource = MyTable
MyGrid.Visible = True

End Sub

Protected Sub MyGrid_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles MyGrid.RowCommand

Dim SelectedRow As Integer
Dim SelectedColumn As Integer

'Re-bind the grid...required to save the formatting of the buttons
MyGrid.DataBind()

SelectedRow = Convert.ToInt32(e.CommandArgument)
SelectedColumn = Convert.ToInt32(e.CommandName)

Me.lblResults.Text = "You selected Column " & SelectedColumn.ToString & ", Row " & SelectedRow.ToString

End Sub
End Class

Check out this thread, see if the posted solution helps:

http://forums.asp.net/thread/1257072.aspx


Curious why do you create GridView columns programatically? You can define the columns in the aspx and still have dynamic table built on the server. I have GridView with linkbuttrons and it works fine. I wonder what happens if you declare ButtonField this way..


Matt M:

Check out this thread, see if the posted solution helps:
http://forums.asp.net/thread/1257072.aspx

Matt,

Thanks for the link. I read through it and found 3 "potential" scenario's I could try that might be a fix for my problem. I tried all 3 and I'm happy to say that one (but only one) worked.

The solution that worked for me was placing this code in my page_load event:
Page.ClientScript.GetPostBackEventReference(me, String.Empty)

It seems that this is a known bug, and according to the post, was supposed to have been fixed in prior releases (I'm on the July release). Is there somewhere where I can log this as a bug, or that it's still a bug?

Anyway, I'm all go again...thank you so much for responding to my original post, I appreciate it.

MJ


StanB:

Curious why do you create GridView columns programatically? You can define the columns in the aspx and still have dynamic table built on the server. I have GridView with linkbuttrons and it works fine. I wonder what happens if you declare ButtonField this way..

I Stan,

Yes, you're right, I could have done it the way you have suggested. The problem in my case is that the number (and type) of columns will change regularly depending on user interaction, so this is why I can't set them up at design time.

MJ

No comments:

Post a Comment