views:

1025

answers:

2

I have a dynamically-created GridView which to which I'm attaching a handler using the AddHandler command.

The problem is that when I try to refer to sender.rows within that function, it won't do anything because it says that sender.rows.count = 0.

I've done enough dynamic form creation that I'm pretty sure that I'm creating the controls, binding them, and adding the handler at the proper points during the page init/load/load_complete.

Also, I have nearly the exact same code-behind on another form that is not dynamic, and it is able to access the values in the rows.

Considering that the RowCommand event is firing, it's clear that I'm clicking on a row. For some reason it's just not in scope for the handler event.

Does anyone have any ideas on how to fix this?

Background: What I really want to do is access the values that are databound to the row. I'm creating a SQLCommand and binding that to the dynamic grid, and I would prefer to talk to the grid's datasource, but that doesn't seem to be possible. Perhaps I'm missing something, but for now it seems that reading the values from the GridView (which I hate doing) is the only thing that works.

Thanks, Shawn

Update (Code):

Create the dynamic view (executed on Load event)

sbFormHTML.AppendLine(String.Format("<tr><td colspan=""2""><asp:GridView ID=""{0}"" runat=""server"" DataKeyNames=""primary_key""><Columns>", dataElement.Attributes.GetNamedItem("name").Value))

sbFormHTML.AppendLine("<asp:BoundField DataField=""primary_key"" Visible=""False"" SortExpression=""primary_key"" />")
sbFormHTML.AppendLine("<asp:CommandField SelectText=""Edit"" ShowSelectButton=""True"" />")
sbFormHTML.AppendLine("<asp:CommandField ShowDeleteButton=""True"" />")

For Each data_item As XmlNode In dataElement.SelectSingleNode("data_items").ChildNodes

    Dim header As String = fnGetAttributeValue(data_item, "label")
    If header = "" Then header = data_item.Attributes.GetNamedItem("dbfield").Value

    sbFormHTML.AppendLine(String.Format("<asp:BoundField DataField=""{0}"" HeaderText=""{1}"" SortExpression=""{0}"">", data_item.Attributes.GetNamedItem("dbfield").Value, header))
    sbFormHTML.AppendLine("</asp:BoundField>")

Next
sbFormHTML.AppendLine("</Columns></asp:GridView>")
sbFormHTML.AppendLine(String.Format("</td></tr>"))

AddHandler:

'bind grid RowCommand function to all dynamic grids
Dim dynamicGrids = findWebControlsRecursive(Page, "^gvDyn")
For Each dynamicGrid As GridView In dynamicGrids
    AddHandler dynamicGrid.RowCommand, AddressOf subHandleRowCommand
    Response.Write(String.Format("{0} has {1} rows<br/>", dynamicGrid.ID, dynamicGrid.Rows.Count))
Next

Attempt to do something with it:

Protected Sub subHandleRowCommand(ByVal sender As GridView, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs)
    'skm
    If e.CommandName = "Select" Then


        Try
            Response.Write(String.Format("{0} has {1} rows<br/>", sender.ID, sender.Rows.Count))

    'Remainder of the code snipped for brevity.

End Sub

Databind the grid:

Protected Sub sbLoadGrid(ByVal gridNode As XmlNode)

    ' Databind a GridView object to its SQL query

    Dim conn As SqlConnection = New SqlConnection('connection string here')
    conn.Open()
    Dim cmd As SqlCommand = New SqlCommand("", conn)
    Dim dbTable As String = gridNode.Attributes.GetNamedItem("dbtable").Value

    cmd.CommandText = String.Format("SELECT {0}ID AS primary_key,", dbTable)
    For Each data_item As XmlNode In gridNode.SelectSingleNode("data_items").ChildNodes
        cmd.CommandText &= String.Format(" {0},", data_item.Attributes.GetNamedItem("dbfield").Value)
    Next

    cmd.CommandText = Regex.Replace(cmd.CommandText, ",$", String.Format(" FROM {0}", dbTable))

    Dim dsGrid As SqlDataReader = cmd.ExecuteReader

    Dim tempGrid As GridView = getControlReference(gridNode.Attributes.GetNamedItem("name").Value)
    tempGrid.DataSource = dsGrid
    tempGrid.AutoGenerateColumns = False

    tempGrid.DataBind()



End Sub
+1  A: 

Since you are creating the gridview control dynamically, the ViewState is not getting persisted and that would explain why the rows.count is coming back as 0 in the EventHandler.

ichiban
+1  A: 

I don't see where the sbloadgrid function is getting called anywhere but I would strongly recommend that you try refactoring the code to a more traditional creation of a GridView, setting it's properties, adding it to a placeholder on the page if you need it to be dynamic.

With the query I would recommend you use parameters in the command text and add them to the sql command. It can still be done dynamically and leaves you open to a lot less problems in the long run then using regexes to contruct your queries.

It's probably not the answer that you wanted but unless you have an incredibly strong reason for keeping the code the way it is I would suggest rewriting it. If you the number of columns you get in your query is known before hand I would even suggest setting that up in your asp page instead of dynamically.

If there are a couple of different formats that you could be showing you can set each of them up on the page and only change only update the datasource and enable one of them dynamically at runtime leaving them disabled and hidden by default.

All of these are probably easier to maintain.

Ryan Roper
I eventually did this, and everything was working out fine. However, the requirements changed and the feature which required this was dropped. Go figure. Anyway, I'm happily at another company now and safe from ASP.NET, in the snuggly world of Python and Django. Yay!
ShawnMilo
Glad I could help.
Ryan Roper