2

Greetings!

I'm still learning about the GridView control and I have one bound to an ObjectDataSource. My Web form looks like this:

<asp:GridView ID="ourGrid" runat="server" DataSourceID="ourDataSource" onrowdatabound="ourGrid_RowDataBound"
              HeaderStyle-CssClass="header_style" AlternatingRowStyle-CssClass="altrow_style"
              ShowFooter="true">
    <columns>
    <asp:BoundField DataField="Name" HeaderText="Full Name" />
    <asp:BoundField DataField="Gender" HeaderText="Gender" />
    <asp:BoundField DataField="BirthYear" HeaderText="Year of Birth" />
    <asp:BoundField DataField="JoinDate" HeaderText="Date Joined" HtmlEncode="false" DataFormatString="{0:d}" />
  </columns>
</asp:GridView>
<asp:ObjectDataSource ID="ourDataSource" runat="server" SelectMethod="GetTopUsers" TypeName="Acme.Model.OurNewObject">
</asp:ObjectDataSource>

It currently generates the following markup:

<table cellpadding="0" cellspacing="0" summary="">
    <thead>
        <tr style="header_style">
            <th scope="col">Full Name</th>
            <th scope="col">Gender</th>
            <th scope="col">Year of Birth</th>
            <th scope="col">Date Joined</th>
        </tr>
    </thead>

    <tfoot>
        <tr>
            <td> </td>
            <td> </td>
            <td> </td>
            <td> </td>
        </tr>
    </tfoot>

    <tbody>
        <tr>
            <td>John Smith</td>
            <td>Male</td>
            <td>1967</td>
            <td>17-6-2007</td>
        </tr>
        <tr class="AspNet-GridView-Alternate altrow_style">
            <td>Mary Kay</td>
            <td>Female</td>
            <td>1972</td>
            <td>15-11-2007</td>
        </tr>
        <tr>
            <td>Bill Jones</td>
            <td>Male</td>
            <td>1970</td>
            <td>23-2-2007</td>
        </tr>
    </tbody>
</table>

There are a few more HTML elements that I'd like to add to the table markup that this GridView control will generate. For starters, I need the TFOOT to look like this:

<tfoot>
    <tr>
        <td colspan="4">
            <div>
                <a class="footerlink_style" title="Newest Members" href="#">Newest Members</a>
                <a class="footerlink_style" title="Top Posters" href="#">Top Posters</a>
            </div>
        </td>
    </tr>
</tfoot>

The links will not contain databound information, but will likely be Hyperlink controls. Is there a way I can specify this at design-time?

Also, for the THEAD, is it possible to specify separate styles for each column header like this in the GridView?

<thead>
    <tr style="header_style">
        <th scope="col" style="col1_style">Full Name</th>
        <th scope="col" style="col2_style">Gender</th>
        <th scope="col" style="col3_style">Year of Birth</th>
        <th scope="col" style="col4_style">Date Joined</th>
    </tr>
</thead>

Finally, is it possible to specifiy the summary attribute of the table like this?

<table cellpadding="0" cellspacing="0" summary="Here is a list of users">

Thanks in advance.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
Bullines
  • 5,626
  • 6
  • 53
  • 93
  • I've added a completed working example that everything on a single page. HTH. – Kev Nov 24 '08 at 20:51
  • Thanks for the pastebins, I'll take a look later today when I get a decent block of free time. – Kev Nov 26 '08 at 14:50

3 Answers3

1

TFOOT Customisation:

The footer will always default to creating the same number of cells as the rest of the gridview. You can override this in code by adding:

protected void OurGrid_RowCreated(object sender, GridViewRowEventArgs e)
{
    if(e.Row.RowType == DataControlRowType.Footer)
    {
        int colSpan = e.Row.Cells.Count;

        for(int i = (e.Row.Cells.Count - 1); i >= 1; i -= 1)
        {
            e.Row.Cells.RemoveAt(i);
            e.Row.Cells[0].ColumnSpan = colSpan;
        }  

        HtmlAnchor link1 = new HtmlAnchor();
        link1.HRef = "#";
        link1.InnerText = "Newest Members";  

        HtmlAnchor link2 = new HtmlAnchor();  
        link2.HRef = "#";
        link2.InnerText = "Top Posters";  

        // Add a non-breaking space...remove the space between & and nbsp;
        // I just can't seem to get it to render in
        LiteralControl space = new LiteralControl("& nbsp;");

        Panel p = new Panel();
        p.Controls.Add(link1);
        p.Controls.Add(space);
        p.Controls.Add(link2);

        e.Row.Cells[0].Controls.Add(p);
    }
}

...and add the onrowcreated attribute to the server control:

<asp:GridView ID="ourGrid" onrowcreated="OurGrid_RowCreated" ...

THEAD styles:

You can specify the header css class for each column in the 'headerstyle-cssclass' for each bound field. For example:

<asp:BoundField headerstyle-cssclass="col1_style1" DataField="Name" HeaderText="Full Name" />    
<asp:BoundField headerstyle-cssclass="col1_style2" DataField="Gender" HeaderText="Gender" />

Table Summary:

Just add the summary attribute to the griview:

<asp:GridView ID="ourGrid" summary="blah" ...

Putting it all together:

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        DataSet ds = CreateDataSet();
        this.gv.DataSource = ds.Tables[0];

        this.gv.DataBind();
        this.gv.HeaderRow.TableSection = TableRowSection.TableHeader;
        this.gv.FooterRow.TableSection = TableRowSection.TableFooter;
    }

    protected void OurGrid_RowCreated(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.Footer)
        {
            int colSpan = e.Row.Cells.Count;

            for (int i = (e.Row.Cells.Count - 1); i >= 1; i -= 1)
            {
                e.Row.Cells.RemoveAt(i);
                e.Row.Cells[0].ColumnSpan = colSpan;
            }

            HtmlAnchor link1 = new HtmlAnchor();
            link1.HRef = "#";
            link1.InnerText = "Newest Members";

            HtmlAnchor link2 = new HtmlAnchor();
            link2.HRef = "#";
            link2.InnerText = "Top Posters";

            LiteralControl l = new LiteralControl("&nbsp;");

            Panel p = new Panel();
            p.Controls.Add(link1);
            p.Controls.Add(l);
            p.Controls.Add(link2);

            e.Row.Cells[0].Controls.Add(p);

        }
    }

    private DataSet CreateDataSet()
    {
        DataTable table = new DataTable("tblLinks");
        DataColumn col;
        DataRow row;

        col = new DataColumn();
        col.DataType = Type.GetType("System.Int32");
        col.ColumnName = "ID";
        col.ReadOnly = true;
        col.Unique = true;
        table.Columns.Add(col);

        col = new DataColumn();
        col.DataType = Type.GetType("System.DateTime");
        col.ColumnName = "Date";
        col.ReadOnly = true;
        col.Unique = false;
        table.Columns.Add(col);

        col = new DataColumn();
        col.DataType = Type.GetType("System.String");
        col.ColumnName = "Url";
        col.ReadOnly = true;
        col.Unique = false;
        table.Columns.Add(col);

        DataColumn[] primaryKeysColumns = new DataColumn[1];
        primaryKeysColumns[0] = table.Columns["ID"];
        table.PrimaryKey = primaryKeysColumns;

        DataSet ds = new DataSet();
        ds.Tables.Add(table);

        row = table.NewRow();
        row["ID"] = 1;
        row["Date"] = new DateTime(2008, 11, 1);
        row["Url"] = "www.bbc.co.uk/newsitem1.html";
        table.Rows.Add(row);

        row = table.NewRow();
        row["ID"] = 2;
        row["Date"] = new DateTime(2008, 11, 1);
        row["Url"] = "www.bbc.co.uk/newsitem2.html";
        table.Rows.Add(row);

        return ds;
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style type="text/css">
    .red
    {
         color: red;
    }
    .olive
    {
        color:Olive;
    }
    .teal
    {
        color:Teal;
    }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:gridview 
        id="gv" 
        autogeneratecolumns="false"
        showheader="true" 
        showfooter="true"
        summary="Here is the news!"
        caption="The Caption"
        captionalign="Top"
        alternatingrowstyle-cssclass="alt_row" 
        useaccessibleheader="true"
        onrowcreated="OurGrid_RowCreated" 
        runat="server">
        <columns>
            <asp:boundfield 
                headertext="ID" 
                headerstyle-cssclass="olive"  
                datafield="id" />
            <asp:hyperlinkfield 
                headertext="Link" 
                headerstyle-cssclass="red" 
                datanavigateurlfields="Url" 
                datanavigateurlformatstring="http://{0}" 
                datatextfield="Url" 
                datatextformatstring="http://{0}" />
            <asp:boundfield 
                headertext="Date"  
                headerstyle-cssclass="teal" 
                datafield="Date"/>
        </columns>
    </asp:gridview>
    </div>
    </form>
</body>
</html>

The above produces the following HTML:

<table cellspacing="0" 
        rules="all" 
        summary="Here is the news!" 
        border="1" 
        id="gv" 
        style="border-collapse:collapse;">

    <caption align="Top">
        The Caption
    </caption>
    <thead>
        <tr>
            <th class="olive" scope="col">ID</th>
            <th class="red" scope="col">Link</th>
            <th class="teal" scope="col">Date</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>
                <a href="http://www.bbc.co.uk/newsitem1.html">
                    http://www.bbc.co.uk/newsitem1.html
                </a>
            </td>
            <td>01/11/2008 00:00:00</td>
        </tr>
        <tr class="alt_row">
            <td>2</td>
            <td>
                <a href="http://www.bbc.co.uk/newsitem2.html">
                    http://www.bbc.co.uk/newsitem2.html
                </a>
            </td>
            <td>01/11/2008 00:00:00</td>
        </tr>
    </tbody>
    <tfoot>
        <tr>
            <td colspan="3">
                <div>
                    <a href="#">Newest Members</a>&nbsp;<a href="#">Top Posters</a>
                </div>
            </td>
        </tr>
    </tfoot>
</table>
Kev
  • 118,037
  • 53
  • 300
  • 385
  • Kev, Appending to the Footer in the RowCreated event works like a charm :) However, I'm unable to get the class set in the THEAD or the Summary to appear in the TABLE tag. – Bullines Nov 24 '08 at 20:30
  • Odd...I can see both in view source just fine. Can you post the GridView so I can see what you're doing? – Kev Nov 24 '08 at 20:38
  • I've posted my code as a reply here: http://stackoverflow.com/questions/315178/aspnet-gridview-newbie-questions-about-tfoot-and-th#315583 – Bullines Nov 24 '08 at 21:54
  • tfoot should have th not td ( working jQuery dataTable so thats how I know :P ) – Aamir Afridi Feb 21 '12 at 12:12
0

It looks like you might have more success with what you're trying to do by using the ListView control. That way you define the markup instead of relying on the GridView to do it right.

gfrizzle
  • 12,419
  • 19
  • 78
  • 104
-1

Footer content will need to be generated on databind. Set a handler for RowDataBound. The logic should look something like this:

if (e.Row.Type == DataControlRowType.Footer)
{
// Do Work
}

To specify different style for the header something like this will do:

<Columns>
  <asp:BoundField DataField="PrimaryKey" HeaderText="TheKey">
    <headerstyle cssclass="Header1" />
  </asp:BoundField>
  <asp:BoundField DataField="Value" HeaderText="AValue">
    <HeaderStyle cssclass="Header2" />
  </asp:BoundField>
  <%-- ... --%>
</Columns>

For the summary part, you can simply have that in the declaration of the GridView control.

<asp:GridView id="theGrid" runat="server" summary="The Summary" >
...
</asp:GridView>

Depending on your validation setup Visual Studio might beef at you, but it will render.

Gavin Miller
  • 43,168
  • 21
  • 122
  • 188