Click here to Skip to main content
15,888,208 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
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:

VB
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

                                'Since this fires before the viewstate is loaded, load the category
                                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
                            'For now, only DataViews/tables are valid data sources
                            Dim drv As DataRowView = e.Row.DataItem

                            If drv IsNot Nothing Then
                                'Get the current category field
                                Dim thiscat As String = dev(GroupByFormatString).toString()


                                'IF the categories do not match, add a new grouping row
                                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

                                    'Store this category in a hidden field that can be accessed during control creation.
                                    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!
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900