Search code examples
asp.netsilverlight

Custom grid control in Silverlight


In one of our migration project we have a Silverlight project. Most of the controls used in that project are custom controls. In one of its functionality, a grid containing the records of child and parent gets loaded. Initially only the parent details gets loaded with one expand symbol next to it. On clicking expand button child details gets loaded.

I need to know what exactly is happening behind the scene when we are clicking on expand button. When child records are more it takes time to load. I tried to debug but no postback call is happening.

Let me know in case you need more detail.

Please guide.


Solution

  • So, assuming you are dumping silverlight?

    Then to nest a grid, you can say drop in a listview, and then inside of the listview, we drop in a grid view. You can try and nest two gridviews, but I find they don't work well, but a listview for the main grid, and then for child grid, then a grid view is just fine.

    So, markup will look say like this (listview, then nested gridview).

       <asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" >
           <ItemTemplate>
              <tr style="">
                <td><asp:Button ID="cmdView" runat="server" Text="+" onclick="cmdView_Click" /></td>
                <td><asp:Label ID="HotelNameLabel" runat="server" Text='<%# Eval("HotelName") %>' /></td>
                <td><asp:Label ID="CityLabel" runat="server" Text='<%# Eval("City") %>' /></td>
                <td><asp:Label ID="ProvinceLabel" runat="server" Text='<%# Eval("Province") %>' /></td>
                <td><asp:Label ID="DescriptionLabel" runat="server" Text='<%# Eval("Description") %>' /></td>
              </tr>
              <tr>
                <td colspan="5">
                   <asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False" 
                     DataKeyNames="ID" CssClass="table table-hover" style="display:none;margin-left:3%;width:97%"  >
                        <Columns>
                            <asp:BoundField DataField="Firstname" HeaderText="Firstname" SortExpression="Firstname" />
                            <asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
                            <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
                               <asp:TemplateField HeaderText="Select">
                                <ItemTemplate>
                                    <asp:CheckBox ID="ckSel" runat="server" OnCheckedChanged="ckSel_CheckedChanged"
                                        AutoPostBack="true"></asp:CheckBox>
                                </ItemTemplate>
                            </asp:TemplateField>
                        </Columns>
                    </asp:GridView>
                </td>
               </tr>
               </ItemTemplate>
           <LayoutTemplate>
            <table id="itemPlaceholderContainer" runat="server" class = "table table-hover" >
                <tr runat="server" style="">
                    <th runat="server">View</th>
                    <th runat="server">HotelName</th>
                    <th runat="server">City</th>
                    <th runat="server">Province</th>
                    <th runat="server">Description</th>
                </tr>
                <tr id="itemPlaceholder" runat="server">
                </tr>
             </table>
           </LayoutTemplate>
        </asp:ListView>
    

    Now to be fair, above is about as much mark-up we would include in a post on SO (any more, and no one will read or bother with this post.

    Ok, so the code to load up the listview (the main part). Would be this:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
        If Not IsPostBack Then
            LoadGrid()
        End If
    
    End Sub
    
    Sub LoadGrid()
        Dim strSQL As String
    
        strSQL = "SELECT * FROM tblHotels WHERE ID in (select hotel_Id from People)
                 ORDER BY HotelName"
    
        Using cmdSQL As New SqlCommand(strSQL, New SqlConnection(My.Settings.TEST4))
    
            cmdSQL.Connection.Open()
    
            ListView1.DataSource = cmdSQL.ExecuteReader
            ListView1.DataBind()
    
        End Using
    
    End Sub
    

    Output:

    enter image description here

    Ok, so now we need the code for the "+" button. When clicked, it will expand, and show the child gridview.

    That code is like this:

    Protected Sub cmdView_Click(sender As Object, e As EventArgs)
    
        Dim cmd As Button = sender
    
        'Dim gVR As ListViewDataItem = ListView1.Items(ListView1.SelectedIndex)
        Dim gVR As ListViewDataItem = cmd.Parent
        Dim gChild As GridView = gVR.FindControl("GridView2")   ' pluck out the grid for this row
    
        If gChild.Style("display") = "normal" Then
            ' if grid is already display, then hide it, and exit
            gChild.Style("display") = "none"
            Exit Sub
        End If
    
        gChild.Style("display") = "normal"
        Dim HotelPK As String = ListView1.DataKeys(gVR.DataItemIndex).Item("ID")
    
        ' only re-load if never loaded (can't re-load else blow out check boxes
    
        If gChild.Rows.Count = 0 Then
            Dim strSQL As String
            strSQL = "SELECT * from People where hotel_id = " & HotelPK
    
            Using cmdSQL As New SqlCommand(strSQL, New SqlConnection(My.Settings.TEST4))
    
                cmdSQL.Connection.Open()
                gChild.DataSource = cmdSQL.ExecuteReader
                gChild.DataBind()
    
            End Using
        End If
    
    End Sub
    

    Note how the child rows are NOT loaded until you click. Clicking on a + button this results in this:

    enter image description here

    And the state of the expand/close does remain intact.

    And thus now if we expand again, then the data does not have to be re-loaded.