Reputation: 6205
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
Upvotes: 1
Views: 2480
Reputation: 333
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.
Upvotes: 1
Reputation: 6210
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.
Upvotes: 1