Nesting a GridView Control Within a Repeater Control [vb.NET]

July 30, 2010

Development

The Scenario

I’ve recently been placed in a scenario where I was required to nest a GridView control within a Repeater control. I thought this would be more straight forward then it ended up being, so I began searching for my elegant solution. Unfortunately this wasn’t as straight forward a task as I thought it would be as step by step tutorial for this process seemed non-existent. This left me experimenting with hours of trial and error before I figured it out. I’m hoping this post will save someone else some time.

Disclaimer: As I am still very much a layman with technology, I’m freely admitting that this may not be the best way to accomplish this task. If someone knows of a better solution, please let me know.

Setting Up The Repeater Control

The first step is to (obviously) set up the Repeater control where the GridView will be nested. The markup for my control looks like this:


<dl>
<asp:Repeater ID="myRepeater" runat="server">
    <ItemTemplate>
        <dt><%#Container.DataItem("WORD")%></dt>
        <dd><%#Container.DataItem("WORD_DEFINITION")%></dd>
        <dd>
            <!-- Where I want the nested GridView -->
        </dd>
    </ItemTemplate>
</asp:Repeater>
</dl>

The codebehind page looks like this:


'Assuming your connection information has be set and stored as the variable "cn"
Dim sql As String = "SELECT WORD, WORD_DEFINITION FROM WORDS"
cmd = New OracleCommand(Sql, cn)
dr = cmd.ExecuteReader()
myRepeater.DataSource = dr
myRepeater.DataBind()

Setting Up The GridView Control

Very basic so far. To add the GridView control within the Repeater we need to do a couple of things to markup:

  1. Add the GridView control where you want it to appear within the Repeater.
  2. Add the OnItemDataBound property to the Repeater tag, and provide a sub/function name for it. For those that might be unaware, the OnItemDataBound property specifies a sub/function to execute with each iteration of the Repeater control.

My markup now looks like this:


<dl>
<asp:Repeater ID="myRepeater" runat="server" OnItemDataBound="getNestedData">
    <ItemTemplate>
        <dt><%#Container.DataItem("WORD")%></dt>
        <dd><%#Container.DataItem("WORD_DEFINITION")%></dd>
        <dd>
            <asp:GridView ID="myGridView" runat="server"></asp:GridView>
        </dd>
    </ItemTemplate>
</asp:Repeater>
</dl>

Making The Magic Happen

In the codebehind page we have to write the the code for the getNestedData sub/function that will bind data to the GridView with each iteration of the Repeater control:


Sub getNestedData(ByVal Sender as Object, ByVal e as RepeaterItemEventArgs)

' ... set data source connection information ...

' Because we're inside of the Repeater control, .NET won't be able to see the GridView Control automatically. You need to explicitly map to the control. This will assign subGridView the properties of myGridView:
Dim subGridView As New GridView
subGridView = e.Item.FindControl(""myGridView")

' Next, we need to query the DataSource to return the data we want to populate the GridView control with. Most likely, we will want to use one of the Repeater control data items in the predicate clause of the query statement, so we'll grab that first. This will assign the variable 'key' whatever the current value of the data item 'word' is.
Dim key As String = e.Item.DataItem("WORD")

'Build the sql statement:
Dim sql As String = "SELECT * FROM WORD_HISTORY WHERE WORD = " & key

'Execute the command:
cmd = New OracleCommand(sql, cn)
dr = cmd.ExecuteReader()

'Now we have the ability to bind the data to the nested GridView Control as if it weren't nested:
subGridView.DataSource = dr
subGridView.DataBind()

'... connection/code clean up ...

End Sub

Coming from a heavy ‘event driven’ programming background, this object based approach seemed foreign to me at first, but in reality the process wasn’t too difficult once I understood what needed to be done.

, ,

No comments yet.

Leave a Reply