tenfour
tenfour

Reputation: 36896

How to use `PlaceHolder` in place of `HtmlTableRow` or `HtmlTableCell`?

I would like to create a user control which contains the following in the ASCX file:

...
<tr runat="server" ID="mytr">
    <td runat="server" ID="myCell1"></td>
    <asp:PlaceHolder runat="server" ID="myPlaceholder"></asp:PlaceHolder>
    <td runat="server" ID="myCell2"></td>
</tr>
...

This generates the following error:

System.Web.UI.HtmlControls.HtmlTableCellCollection must have items of type 'System.Web.UI.HtmlControls.HtmlTableCell'. 'asp:PlaceHolder' is of type 'System.Web.UI.WebControls.PlaceHolder'.

The reason for the PlaceHolder is I would like to dynamically generate that cell (for example choosing between TD and TH, or choosing whether to create it at all.

Is there an easy way to do this? Or maybe I should just create my own custom control which inherits HtmlTableCell?

I have noticed that viewstate for certain table elements are keyed by the ordinal (index into child control collection), which means I also sometimes cannot dynamically generate cells when I would expect to be able to. Is there some general best practice with regards to this?

I have also considered always creating the TD, but just hiding it. The problem is that I use rowspan on a previous row, meaning different rows will render different numbers of cells. This is conditional and can change between postbacks (by enabling / disabling a row).

Upvotes: 2

Views: 5010

Answers (4)

Martin Belcher - AtWrk
Martin Belcher - AtWrk

Reputation: 4569

The solution I use when I run into this is to replace the <tr> with an <asp:literal> and write the HTML for the table row myself.

Example:

<asp:literal runat="server" ID="trRow" Mode="PassThrough" />
    <td runat="server" ID="myCell1"></td>
    <asp:PlaceHolder runat="server" ID="myPlaceholder"></asp:PlaceHolder>
    <td runat="server" ID="myCell2"></td>
</tr>

Then in the code behind

Literal trRow = (Literal)e.Item.FindControl("trRow");
// ... some code here decides on CSS class I want to use
trRow.Text = string.Format("<tr class=\"{0}\">", strCssClass);

Upvotes: 0

tenfour
tenfour

Reputation: 36896

I managed to solve it by making a simple custom control:

public class HtmlTableCellPH : HtmlTableCell
{
    public HtmlTableCellPH()
    {
    }

    public HtmlTableCellPH(string tagName)
        : base(tagName)
    {
    }

    public override void RenderControl(HtmlTextWriter writer)
    {
        this.RenderChildren(writer);
    }
}

And now the ascx is:

...
<tr runat="server" ID="mytr">
    <td runat="server" ID="myCell1"></td>
    <ns:HtmlTableCellPH runat="server" ID="myPlaceholder"></ns:HtmlTableCellPH>
    <td runat="server" ID="myCell2"></td>
</tr>
...

Upvotes: 0

Alexander Schimpf
Alexander Schimpf

Reputation: 2392

There are a couple of ways you could get around this.

1. Remove the runat="server" attributes from the table and tr tags. The down side to this method is that you won't be able to modify those tags from the server-side. You will still be able to modify any td tags though.

2. Generate the entire table dynamically from server-side code.

HTML

<table runat="server" id="Table1">
</table>

C# Server-side code

HtmlTableRow row = new HtmlTableRow();
HtmlTableCell cell = new HtmlTableCell();
cell.InnerText = "Text goes here.";
row.Cells.Add(cell);

this.Table1.Rows.Add(row);

Upvotes: 1

Kapil Khandelwal
Kapil Khandelwal

Reputation: 16144

You can use ASP.net Table Webcontrol for creating your table dynamically (if you consider of generating whole table from your code.)

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.table.aspx

Upvotes: 1

Related Questions