I created a custom gridview control that allows the user to group together similar values. So say you had a list of customers from different states and you wanted to list the customers by state. My gridview would go through the data, find rows with new state values, create a dynamic row and insert it above the current row. So :
Alabama
Bob Jonson 123 Main street
Fred Newber 533 Oak Street
Arizona
Dick James 555 Ledge Hill
Jane Smith 123 Park St
I initially create the dynamic rows in an override of the OnRowDataBound event. Then I re-create the rows on postback in an override of the OnRowCreated event. The code works great.
THE PROBLEM shows up when I try to add other controls to the gridview. So say I create a template column with a "New order from this customer" button in front of their name. When I click the button, nothing happens. When I click it again, the RowCommand event fires.
I've narrowed the problem down but have been unable to solve it. The ID's generated for the buttons in the template column CHANGE on postback. So when the data is bound, the control id will be "ctl00_ContentPlaceHolder1_ExtraGridView1_ctl04_LinkButton1". But on postback the id changes to "ctl00_ContentPlaceHolder1_ExtraGridView1_ctl07_LinkButton1". After the initial postback the ID no longer changes.
Something is happening on postback that doesn't happen when the data is bound but I can't seem to figure it out. Here is the code I'm using:
Imports Microsoft.VisualBasic
Imports System.ComponentModel
Imports System.Data
Imports kExchangeWebControls
Namespace CallCenter
Public Class GroupByGrid
Inherits GridView
Dim lastcat As String = ""
<Browsable(True), DefaultValue(GetType(String), "")> _
Public Property GroupByColumnName() As String
Get
Return ViewState("GROUPCOLUMN")
End Get
Set(ByVal value As String)
ViewState("GROUPCOLUMN") = value
End Set
End Property
<Browsable(True), DefaultValue(GetType(String), "{0}")> _
Public Property GroupByFormatString() As String
Get
If ViewState("GROUPBYFORMAT") Is Nothing Then
Return "{0}"
Else
Return ViewState("GROUPBYFORMAT")
End If
End Get
Set(ByVal value As String)
ViewState("GROUPBYFORMAT") = value
End Set
End Property
<Browsable(True), DefaultValue(GetType(String), "Uncategorized")> _
Public Property GroupByUncategorizedName() As String
Get
If ViewState("GROUPBYUNAME") Is Nothing Then
Return "Uncategorized"
Else
Return ViewState("GROUPBYUNAME")
End If
End Get
Set(ByVal value As String)
ViewState("GROUPBYUNAME") = value
End Set
End Property
Dim GroupStyle As Style
<Browsable(True), Category("Appearance"), Description(""), PersistenceMode(PersistenceMode.Attribute), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), NotifyParentProperty(True)> _
Public ReadOnly Property GroupByCellStyle() As Style
Get
If GroupStyle Is Nothing Then
GroupStyle = New Style()
End If
Return GroupStyle
End Get
End Property
Protected Overrides Sub OnRowCreated(ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
MyBase.OnRowCreated(e)
If Not rebind Then
If Not Me.DesignMode Then
If e.Row.RowType = DataControlRowType.DataRow Then
If GroupByColumnName IsNot Nothing Then
If GroupByColumnName.Trim <> "" Then
Dim thiscat As String = System.Web.HttpContext.Current.Server.UrlDecode(System.Web.HttpContext.Current.Request.Form(Me.ID & "_ROW" & e.Row.RowIndex))
If thiscat IsNot Nothing Then
If lastcat.ToUpper.Trim <> thiscat.ToUpper.Trim Then
Dim gvr As New GridViewRow(e.Row.RowIndex, -1, DataControlRowType.DataRow, DataControlRowState.Normal)
Dim c As New TableCell
c.ApplyStyle(GroupByCellStyle)
Dim l As New LiteralControl
If thiscat.Trim <> "" Then
l.Text = thiscat
Else
l.Text = GroupByUncategorizedName
lastcat = l.Text
End If
l.Text &= "<input type=""hidden"" name=""" & Me.ID & "_ROW" & e.Row.RowIndex & """ value=""" & System.Web.HttpContext.Current.Server.UrlEncode(thiscat) & """/>"
c.ColumnSpan = e.Row.Cells.Count
c.Controls.Add(l)
gvr.Cells.Add(c)
Dim tbl As Table = Me.Controls(0)
Dim gvrcpy = e.Row
tbl.Rows.Remove(e.Row)
tbl.Rows.Add(gvr)
tbl.Rows.Add(gvrcpy)
lastcat = thiscat
End If
End If
End If
End If
End If
End If
End If
End Sub
Protected Overrides Sub OnRowDataBound(ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
MyBase.OnRowDataBound(e)
If e.Row.RowType = DataControlRowType.DataRow Then
If Not Me.DesignMode Then
If GroupByColumnName IsNot Nothing Then
If GroupByColumnName.Trim <> "" Then
Dim drv As DataRowView = e.Row.DataItem
If drv IsNot Nothing Then
Dim thiscat As String = dev(GroupByFormatString).toString()
If lastcat.ToUpper.Trim <> thiscat.ToUpper.Trim Then
Dim gvr As New GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal)
Dim c As New TableCell
c.ApplyStyle(GroupByCellStyle)
If thiscat.Trim <> "" Then
c.Text = thiscat
Else
c.Text = GroupByUncategorizedName
lastcat = c.Text
End If
c.Text &= "<input type=""hidden"" name=""" & Me.ID & "_ROW" & e.Row.RowIndex & """ value=""" & System.Web.HttpContext.Current.Server.UrlEncode(thiscat) & """/>"
c.ColumnSpan = e.Row.Cells.Count
gvr.Cells.Add(c)
Dim tbl As Table = Me.Controls(0)
tbl.Rows.AddAt(tbl.Rows.GetRowIndex(e.Row), gvr)
lastcat = thiscat
End If
End If
End If
End If
End If
End If
End Sub
Private rebind As Boolean = False
Private Sub ExtraGridView_DataBinding(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.DataBinding
rebind = True
End Sub
End Class
End Namespace
Thanks in advance for any help you can offer!