views:

152

answers:

3

From an MSDN article on the subject, we can see that we create a TableHeaderRowthat contains TableHeaderCells.

But they add the table header like this:

myTable.Row.AddAt(0, headerRow);

which outputs the HTML:

<table id="Table1" ... > 
<tr> 
    <th scope="column" abbr="Col 1 Head">Column 1 Header</th>
    <th scope="column" abbr="Col 2 Head">Column 2 Header</th>
    <th scope="column" abbr="Col 3 Head">Column 3 Header</th> 
</tr>
<tr> 
    <td>(0,0)</td>
    <td>(0,1)</td>
    <td>(0,2)</td>
</tr>

...

and it should have <thead> and <tbody> (so it works seamless with tablesorter) :)

<table id="Table1" ... > 
<thead>
<tr> 
    <th scope="column" abbr="Col 1 Head">Column 1 Header</th>
    <th scope="column" abbr="Col 2 Head">Column 2 Header</th>
    <th scope="column" abbr="Col 3 Head">Column 3 Header</th> 
</tr>
</thead>
<tbody>
<tr> 
    <td>(0,0)</td>
    <td>(0,1)</td>
    <td>(0,2)</td>
</tr>
    ...
    </tbody>

the HTML aspx code is

<asp:Table ID="Table1" runat="server" />

How can I output the correct syntax?


Just as information, the GridViewcontrol has this built in as we just need to set the Accesbility and use the HeaderRow

gv.UseAccessibleHeader = true;
gv.HeaderRow.TableSection = TableRowSection.TableHeader;
gv.HeaderRow.CssClass = "myclass";

but the question is for the Table control.

A: 

I was going to suggest that you try the declarative syntax, but I now know what you mean; the following code...:

<asp:Table runat="server" ID="sometable">
    <asp:TableHeaderRow BackColor="#ADD9E6">
        <asp:TableHeaderCell ID="DataHeader" CssClass="Heading1" Text="Data Header" />
    </asp:TableHeaderRow>
    <asp:TableRow>
        <asp:TableCell>Data</asp:TableCell>
    </asp:TableRow>
</asp:Table>

... produced similar results to what you posted:

<table id="sometable" border="0">
<tr style="background-color:#ADD9E6;">
    <th id="DataHeader" class="Heading1">Data Header</th>
</tr><tr>
    <td>Data</td>
</tr>
</table>

Perhaps a custom control could be created to solve your problem? Seems like overkill, but at least you can control what the generated output is.

Another option is to inherit from the System.Web.UI.WebControls.Table class, and override how the table is rendered.

David Ipsen
I can't use the declarative syntax :( it's a dynamic table, only on RunTime I know how many what what is the columns all about... this idea uses an XML that is generated by a designer to create the "Grid"
balexandre
A: 

If you could use a DataGrid when you name the columns in the template it will produce a thead and tbody appropriately.

Corith Malin
DataGrid does not do it by default
balexandre
A: 

Just found a way to do this, we do need to use our own controls that inherit from the base control, for example a Table

public class myTable : System.Web.UI.WebControls.Table
{
    protected override void OnPreRender(EventArgs e)
    {
        Table table = Controls[0] as Table;

        if (table != null && table.Rows.Count > 0)
        {
            // first row is the Table Header <thead>
            table.Rows[0].TableSection = TableRowSection.TableHeader;
            // last row is the Footer Header <tfoot> (comment for not using this)
            table.Rows[table.Rows.Count - 1].TableSection = TableRowSection.TableFooter;

            FieldInfo field = typeof(WebControl).GetField("tagKey", BindingFlags.Instance | BindingFlags.NonPublic);
            foreach (TableCell cell in table.Rows[0].Cells)
                field.SetValue(cell, HtmlTextWriterTag.Th);
        }
        base.OnPreRender(e);
    }
}

works fine with DataGrid as well

public class myDataGrid : System.Web.UI.WebControls.DataGrid 
{
    protected override void OnPreRender(EventArgs e)
    {
        Table table = Controls[0] as Table;

        if (table != null && table.Rows.Count > 0)
        {
            // first row is the Table Header <thead>
            table.Rows[0].TableSection = TableRowSection.TableHeader;
            // last row is the Footer Header <tfoot> (comment for not using this)
            table.Rows[table.Rows.Count - 1].TableSection = TableRowSection.TableFooter;

            FieldInfo field = typeof(WebControl).GetField("tagKey", BindingFlags.Instance | BindingFlags.NonPublic);
            foreach (TableCell cell in table.Rows[0].Cells)
                field.SetValue(cell, HtmlTextWriterTag.Th);
        }
        base.OnPreRender(e);
    }
}

then for example you just need to use it instead the base control:

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        myGridView dg = new myGridView();
        dg.DataSource = new string[] { "1", "2", "3", "4", "5", "6" };
        dg.DataBind();

        ph.Controls.Add(dg);
    }
}

and in aspx page, just add a place holder like:

<asp:PlaceHolder ID="ph" runat="server" />

full example in pastebin

balexandre