LinkButtons Created Dynamically in a Repeater Don't Fire ItemCommand Event
<p>I've got a repeater that's used to display the output of a dynamic report that takes criteria from webcontrols on the page.</p>

<p>Within the repeater's ItemDataBound method I'm adding controls (Linkbuttons for sorting by column values) dynamically to the header of the repeater based on values selected in a checkbox list and at this point setting the CommandArgument and CommandName properties of the linkbuttons.</p>

<p>The issue is that when the linkbuttons are clicked they don't fire the ItemCommand event although they are clearly being correctly created and added to the header (there is some additional code to set the cssClass, text etc. and this works as expected.) The first column header in the repeater is set in the markup and the itemcommand event fires correctly on this one only. When the other column headers are clicked the repeater rebinds as programmed, but the columns are not dynamically re-generated.</p>

<p>I would really appreciate somebody explaining what I'm doing wrong - afaik I'm following the approved way of doing this :-(</p>

<p>Simplified code follows:</p>

<p>Nightmare.ascx</p>

<pre><code>&lt;asp:repeater runat="server" id="rptReport" OnItemDataBound="rptResults_ItemDataBound" OnItemCommand="rptResults_ItemCommand" EnableViewState="true"&gt;
&lt;headertemplate&gt;
&lt;table&gt;
&lt;tr runat="Server" id="TRDynamicHeader"&gt;
&lt;th&gt;
&lt;!-- This one works --&gt;
&lt;asp:Linkbutton runat="server" CommandName="sort" commandArgument='&lt;%# Eval("Name")%?' /&gt;
&lt;/th&gt;
&lt;!-- additional header cells get added dynamically here --&gt;
&lt;/tr&gt;
&lt;/headertemplate&gt;
&lt;itemTemplate&gt;
&lt;td&gt;&lt;%# Eval("Name")&lt;/td&gt;
...
&lt;/itemTemplate&gt;

&lt;/asp:repeater&gt;
</code></pre>

<p>Nightmare.ascx.cs</p>

<pre><code>protected void PageLoad(object sender, eventArgs e){
if (! isPostback){
setupGui();//just binds dropdowns etc. to datasources
}
}

protected void btnRunReport_Click(...){
List&lt;ReportLines&gt; lstRep = GetReportLines();

rptReport.DataSource = lstRep;
repReport.DataBind();
}

protected void rptReport_ItemDataBound (...){
if (e.Item.ItemType == ListItemType.Header)
{
foreach (ListItem li in chbxListBusFuncs.Items)
{
if (li.Selected)               
{
th = new HtmlTableCell();
lb = new LinkButton();
lb.CssClass = "SortColHeader";
lb.CommandArgument = li.Text.Replace(" ", "");
lb.CommandName = "sort";
lb.Text = li.Text;
th.Controls.Add(lb);


((HtmlTableRow)e.Item.FindControl("TRDynamicHeader")).Cells.Add(th);
}
}
}

if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
//Row level customisations, totals calculations etc.

}
}

&lt;!-- this only gets called when the 'hardcoded' linkbutton in the markup is clicked.
protected void rptReport_ItemCommand(object sender, Eventargs e){
lblDebug.Text = string.Format("Well? What's Happening? -&gt; {0}:{1}", e.CommandName, e.CommandArgument.ToString());
}
</code></pre>

<p>(The only thing that can call the runreport routine is a single button on the page, not shown in the code snippet above.)</p>
