views:

3124

answers:

4

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.

A: 

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
I tried:<asp:BoundField DataField="VirusName" HeaderText="Name"> <headerstyle cssclass="col1_style" /></asp:BoundField>and <asp:BoundField DataField="VirusName" HeaderText="Name" HeaderStyle-CssClass="col1_style" />But neither seem to work for me.
Bullines
Adding summary text still results in <table cellspacing="0" cellpadding="0" summary="">
Bullines
+1  A: 

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"&gt;

<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"&gt;
<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"&gt;
        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"&gt;
        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
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
Odd...I can see both in view source just fine. Can you post the GridView so I can see what you're doing?
Kev
I've posted my code as a reply here: http://stackoverflow.com/questions/315178/aspnet-gridview-newbie-questions-about-tfoot-and-th#315583
Bullines
A: 

Here's what I have thus far:

<asp:GridView
        ID="ourGrid"
        runat="server"
        DataSourceID="ourDataSource"
        AutoGenerateColumns="false"
        ShowHeader ="true"
        ShowFooter="true" 
        summary="User List"
        Caption="User List"
        CaptionAlign="Top"
        HeaderStyle-CssClass="header_style"
        AlternatingRowStyle-CssClass="altrow_style"
        onrowdatabound="ourGrid_RowDataBound"
        onrowcreated="ourGrid_RowCreated">
    <columns>
        <asp:BoundField
                HeaderText="Full Name"
                HeaderStyle-CssClass="namecol_style"
                DataField="Name" />
        <asp:BoundField
                HeaderText="Gender"
                HeaderStyle-CssClass="gendercol_style"
                DataField="Gender" />
        <asp:BoundField
                HeaderText="Year of Birth"
                HeaderStyle-CssClass="birthyear_style"
                DataField="BirthYear" />
        <asp:BoundField
                HeaderText="Date Joined"
                HeaderStyle-CssClass="joindate_style"
                DataField="JoinDate"
                HtmlEncode="false"
                DataFormatString="{0:d}" />
    </columns>
</asp:GridView>
<asp:ObjectDataSource
        ID="ourDataSource"
        runat="server"
        SelectMethod="GetTopUsers"
        TypeName="Acme.Model.OurNewObject" />

This produces 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 colspan="4">
                <div>
             <a href="#">Newest Members</a>
                    <a href="#">Top Posters</a>
                </div>
            </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>

For some strange reason, I just cannot find a way to get the style for the TH's in the THEAD to appear, nor can I get the SUMMARY attribute of the TABLE tag or the CAPTION section to appear. I'm using this in a User Control; could this be a factor?

Bullines
There's a bit of weirdness going on here. I've pretty much replicated your gridview (including placing in a usercontrol) but the layout I get is working just fine.
Kev
Could it be because the data source for the GridView is an XmlDataSource?
Bullines
Wouldn't have thought so. Can you paste your Page, Codebehind and a sample of the xml into pastebin and drop a link to it here?
Kev
User Control: http://pastebin.com/med537a8User Control Code Behind: http://pastebin.com/ma1fe286Page: http://pastebin.com/m275962fdI made a typo...we're using an ObjectDataSource, not an Xml one. We have a simple object containing four properties; Name, Gender, BirthYear, and JoinDate. Thx.
Bullines
A: 

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