Wednesday, February 01, 2012

GridView Cell click refreshes detail Gridview

You may have used Master and Detail Gridview to show selected row data in detail Gridview. But what if you have to click on selected cell in one Gridview which happen to result filtered result set in another Gridview.

I will be using two Gridview, AJAX, and a tiny client side JavaScript for this requirement. I will further modify the previous example and add new controls for this requirement. Here is the new code which is self explanatory

WebForm1.aspx

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="WebApplication1.WebForm1" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Test Multi Header Gridview</title>
 
     <div id="Div1" runat="server">
     <script language="javascript" type="text/javascript">
 
         function ShowGrid(type, value) {
             document.getElementById("<%=txtType.ClientID%>").value = type;
             document.getElementById("<%=txtValue.ClientID%>").value = value;
             document.getElementById("dataInfo").innerHTML = "Selection Type:" + type + ", Value: " + value;       
             document.getElementById("<%=btnShowData.ClientID%>").click();                 
         }
 
    </script>
    </div>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server" />
 
    <div id="searchArea" align="center">
        <asp:Button ID="btnGetData" runat="server" Text="Get Data" />
        <br />
          Export Format 
                      <asp:DropDownList ID="ddlExportData" runat="server" CssClass="clsCombo" >
                            <asp:ListItem Value="CSV" Text="CSV"/>
                            <asp:ListItem Value="XLS" Text="Excel"/>
                            <asp:ListItem Value="XML" Text="XML"/>
                        </asp:DropDownList>&nbsp;
                        <asp:Button ID="btnExportData" runat="server" CausesValidation="false" Text="Export Data" />                                                                                             
 
               <div style="width:0;height:0;display:none;visibility:hidden;">
                            <asp:TextBox ID="txtType" runat="server" Width="0" Height="0" />
                            <asp:TextBox ID="txtValue" runat="server" Width="0" Height="0" />                        
                            <asp:Button ID="btnShowData" runat="server" Width="0" Height="0" />                                                                                                              
               </div>
    </div>
 
    <div align="center">
 
      <asp:GridView ID="gvwRecord" runat="server"  AutoGenerateColumns="false" FooterStyle-Wrap="false" 
                            EmptyDataText="No data is available for this search criteria." DataKeyNames="ID" AllowPaging="false"   > 
             <Columns>                                                                                                   
                <asp:BoundField DataField="ID" HeaderText="ID" ItemStyle-HorizontalAlign="left"/> 
                <asp:BoundField DataField="Name" HeaderText="Name"  ItemStyle-HorizontalAlign="left" ItemStyle-Wrap="false" /> 
                 <asp:TemplateField HeaderText="Age" ItemStyle-HorizontalAlign="Right" HeaderStyle-HorizontalAlign="Center" >
                    <ItemTemplate>
                        <asp:HyperLink ID="hplAge" NavigateUrl="#"  runat="server" Text='<%# Eval("Age")%>' /> 
                    </ItemTemplate>
                </asp:TemplateField>                
                <asp:TemplateField HeaderText="Sex" ItemStyle-HorizontalAlign="Right" HeaderStyle-HorizontalAlign="Center" >
                    <ItemTemplate>
                        <asp:HyperLink ID="hplSex" NavigateUrl="#"  runat="server" Text='<%# Eval("Sex")%>' /> 
                    </ItemTemplate>
                </asp:TemplateField>    
                <asp:BoundField DataField="Title" HeaderText="Title" ItemStyle-Wrap="false"/>                
            </Columns>
        </asp:GridView>
 
 
 
        <br /><br />              
        <b id="dataInfo"></b>  <br />          
        <asp:UpdatePanel ID="UpdatePanelX" runat="server" UpdateMode="Conditional">  
            <ContentTemplate>                                            
            <asp:GridView ID="gvwRecordDetail" runat="server"  AutoGenerateColumns="false" FooterStyle-Wrap="false" 
                            EmptyDataText="No data is available" DataKeyNames="ID" AllowPaging="false"   > 
                <Columns>                                                                                                   
                <asp:BoundField DataField="ID" HeaderText="ID" ItemStyle-HorizontalAlign="left"/> 
                <asp:BoundField DataField="Name" HeaderText="Name"  ItemStyle-HorizontalAlign="left" ItemStyle-Wrap="false" />                                 
                <asp:BoundField DataField="Title" HeaderText="Title" ItemStyle-Wrap="false"/>                
            </Columns>
            </asp:GridView>
                </ContentTemplate>
                <Triggers>               
                    <asp:AsyncPostBackTrigger ControlID="btnShowData" EventName="Click" />                                                                                     
                </Triggers>
       </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

 

WebForm1.aspx.vb

Public Class WebForm1
    Inherits System.Web.UI.Page
 
#Region "Main GridView"
    Protected Sub btnGetData_Click(sender As Object, e As EventArgs) Handles btnGetData.Click
        Dim tst As New TestRecord
        Dim recs As List(Of TestRecord) = tst.LoadData
        Session("Data") = recs
        gvwRecord.DataSource = recs
        gvwRecord.DataBind()
        gvwRecordDetail.Visible = False
 
    End Sub
 
    Private Sub gvwRecord_RowCreated(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvwRecord.RowCreated
        If e.Row.RowType = DataControlRowType.Header Then
            Dim headerCell1 As TableCell = New TableCell()
            Dim headerCell2 As TableCell = New TableCell()
 
            headerCell1.ColumnSpan = 3
            headerCell1.Text = "Main Header 1"
            headerCell1.BackColor = Drawing.Color.LightGray
            headerCell1.HorizontalAlign = HorizontalAlign.Center
 
            headerCell2.ColumnSpan = 2
            headerCell2.Text = "Main Header 2"
            headerCell2.BackColor = Drawing.Color.LightGray
            headerCell2.HorizontalAlign = HorizontalAlign.Center
 
            Dim rowHeader1 As GridViewRow = New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal)
            rowHeader1.Cells.Add(headerCell1)
            rowHeader1.Cells.Add(headerCell2)
            rowHeader1.ForeColor = Drawing.Color.Black
            rowHeader1.Font.Bold = True
            rowHeader1.Visible = True
            gvwRecord.Controls(0).Controls.AddAt(0, rowHeader1)
 
            Dim fields2 As TableCellCollection = e.Row.Cells
            Dim headerCell11 As TableCell = New TableCell()
            Dim headerCell12 As TableCell = New TableCell()
 
            headerCell11.ColumnSpan = 2
            headerCell11.Text = "ID and Name"
            headerCell11.BackColor = Drawing.Color.Maroon
 
            headerCell12.ColumnSpan = 3
            headerCell12.Text = "Age and Sex"
            headerCell12.BackColor = Drawing.Color.Maroon
 
            Dim rowHeader2 As GridViewRow = New GridViewRow(1, 1, DataControlRowType.Header, DataControlRowState.Normal)
            rowHeader2.Cells.Add(headerCell11)
            rowHeader2.Cells.Add(headerCell12)
 
            rowHeader2.Font.Size = 12
            rowHeader2.ForeColor = Drawing.Color.White
            rowHeader2.HorizontalAlign = HorizontalAlign.Center
            rowHeader2.Visible = True
            rowHeader2.Font.Bold = True
            gvwRecord.Controls(0).Controls.AddAt(1, rowHeader2)
 
        ElseIf e.Row.RowType = DataControlRowType.Footer Then
            Dim footerCell1 As TableCell = New TableCell()
            Dim footerCell2 As TableCell = New TableCell()
            Dim footerCell3 As TableCell = New TableCell()
            Dim footerCell4 As TableCell = New TableCell()
 
            Dim dataRecs As List(Of TestRecord) = Nothing
            Dim totalRec As Integer = 0
            Dim totalMale As Integer = 0
            Dim totalFemale As Integer = 0
            Dim totalAgeBelow30 As Integer = 0
            Dim totalAgeAbove30 As Integer = 0
 
 
            If Session("Data") IsNot Nothing Then
                dataRecs = DirectCast(Session("Data"), List(Of TestRecord))
                If Not dataRecs Is Nothing AndAlso dataRecs.Count > 0 Then
                    totalRec = dataRecs.Count
                    Dim list1 = From r As TestRecord In dataRecs Where r.Sex = "Male"
                    totalMale = list1.Count
 
                    Dim list2 = From r As TestRecord In dataRecs Where r.Sex = "Female"
                    totalFemale = list2.Count
 
                    Dim list3 = From r As TestRecord In dataRecs Where r.Age < 30
                    totalAgeBelow30 = list3.Count
 
                    Dim list4 = From r As TestRecord In dataRecs Where r.Age >= 30
                    totalAgeAbove30 = list4.Count
 
                End If
            End If
 
            footerCell1.Text = "Summary"
            footerCell2.Text = "Age [< 30yrs: " & totalAgeBelow30.ToString() & "] [>=30yrs:" & totalAgeAbove30.ToString() & "]"
            footerCell3.ColumnSpan = 2
            footerCell3.Text = "Male: " & totalMale.ToString() & " Female:" & totalFemale.ToString()
            footerCell4.Text = "Total Count:" & totalRec.ToString()
 
            Dim rowFooter1 As GridViewRow = New GridViewRow(gvwRecord.Rows.Count + 3, 0, DataControlRowType.Footer, DataControlRowState.Normal)
            rowFooter1.Cells.Add(footerCell1)
            rowFooter1.Cells.Add(footerCell2)
            rowFooter1.Cells.Add(footerCell3)
            rowFooter1.Cells.Add(footerCell4)
            rowFooter1.ForeColor = Drawing.Color.Black
            rowFooter1.BackColor = Drawing.Color.LightGray
            rowFooter1.HorizontalAlign = HorizontalAlign.Left
            rowFooter1.Font.Bold = True
            rowFooter1.Visible = True
 
            For cellCount As Integer = 0 To rowFooter1.Cells.Count - 1
                rowFooter1.Cells(cellCount).Wrap = False
            Next
            gvwRecord.Controls(0).Controls.AddAt(gvwRecord.Rows.Count + 3, rowFooter1)
 
        End If
    End Sub
 
    Private Sub gvwRecord_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvwRecord.RowDataBound
        If e.Row.RowType = DataControlRowType.DataRow Then
            Dim paramString As String = ""
            Dim value As String = ""
 
            value = CType(e.Row.Cells(2).FindControl("hplAge"), HyperLink).Text
            paramString = "javascript:ShowGrid('Age'," & value & ");"
            CType(e.Row.Cells(2).FindControl("hplAge"), HyperLink).Attributes.Add("onclick", paramString)
 
            value = CType(e.Row.Cells(3).FindControl("hplSex"), HyperLink).Text
            paramString = "javascript:ShowGrid('Sex','" & value & "');"
            CType(e.Row.Cells(3).FindControl("hplSex"), HyperLink).Attributes.Add("onclick", paramString)
 
        End If
    End Sub
 
    Private Sub btnShowData_Click(sender As Object, e As System.EventArgs) Handles btnShowData.Click
        Dim typeName As String = Me.txtType.Text
        Dim value As String = Me.txtValue.Text
        Dim testRecs As List(Of TestRecord) = Nothing
        Dim filteredRecs As List(Of TestRecord) = Nothing
 
        testRecs = DirectCast(Session("Data"), List(Of TestRecord))
 
        If typeName = "Age" Then
            Dim recList = From r As TestRecord In testRecs Where r.Age = CInt(value)
            filteredRecs = recList.ToList
        ElseIf typeName = "Sex" Then
            Dim recList = From r As TestRecord In testRecs Where r.Sex.Equals(value)
            filteredRecs = recList.ToList
        End If
 
        Me.gvwRecordDetail.Visible = True
        Me.gvwRecordDetail.DataSource = filteredRecs
        Me.gvwRecordDetail.DataBind()
 
    End Sub
#End Region
 
#Region "Exports"
    Private Sub btnExportData_Click(sender As Object, e As System.EventArgs) Handles btnExportData.Click
        If Me.gvwRecord.Rows.Count > 0 Then
            Select Case Me.ddlExportData.SelectedItem.Value.ToUpper()
                Case "CSV"
                    ExportDataToCSV()
 
                Case "XLS"
                    ExportDataToExcel()
 
                Case "XML"
                    ExportToXML()
            End Select
        Else
            Response.Write("No Data available for export")
        End If
    End Sub
 
    Private Sub ExportDataToCSV()
        Dim fileName As String = "FileName_" & Format(Now, "yyyyMMddhhmms") & ".csv"
        Dim localGridView As GridView = GetLocalMktSourceSummaryGridView()
 
        If localGridView IsNot Nothing AndAlso localGridView.Rows.Count < 65536 Then
            HttpContext.Current.Response.Clear()
            ' Set the response headers to fit our CSV file 
            HttpContext.Current.Response.ContentType = "text/plain"
            HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" & fileName)
 
            Using writer As New System.IO.StreamWriter(HttpContext.Current.Response.OutputStream)
                Dim columnHeader As String = String.Empty
                For i As Integer = 0 To localGridView.Columns.Count - 1
                    columnHeader += localGridView.Columns(i).HeaderText & IIf(i < localGridView.Columns.Count - 1, ",", "").ToString()
                Next
 
                writer.WriteLine(columnHeader)
                'writer.WriteLine(AddCSVHeaderRow()) ' Only if you need custom headers to be added
                ' Add all the data rows 
                For Each row As GridViewRow In localGridView.Rows
                    writer.WriteLine(GetCSVLine(row.Cells))
                Next
            End Using
 
            ' End the current response. Otherwise, excel will open with the whole page inside.
            HttpContext.Current.Response.End()
 
        Else
            Response.Write("Too many rows - Export to Excel not possible")
        End If
 
    End Sub
 
    Private Function GetLocalMktSourceSummaryGridView() As GridView
        Dim rptData As List(Of TestRecord) = Nothing
        Dim localGridView As New GridView
        If Session("Data") IsNot Nothing Then rptData = DirectCast(Session("Data"), List(Of TestRecord))
        localGridView.AllowPaging = False
        localGridView.AllowSorting = False
        localGridView.AutoGenerateColumns = False
 
        localGridView.DataSource = rptData
 
        Dim col01