ASP.NET OnClick not firing in Repeater.ItemTemplate that has a custom control
Title is a bit of a mouthful, but I'm a bit stuck on this issue.
I have a search result page with has a custom control that has a Repeater
. The ItemTemplate
in the repeater is a PlaceHolder
so I can construct the Item in a particular format; more specifically, I have a string of 'diseases' that come in the form of Disease1|disease2|disease3
and need to be given links for each disease.
Now for some code:
The following is the SearchResultControl.ascx
<asp:Panel ID="SearchResultPanel" runat="server" ScrollBars="Auto">
<asp:Repeater ID="Repeater1" runat="server"
onitemcreated="Repeater1_ItemCreated"
onitemcommand="Repeater1_ItemCommand">
<ItemTemplate>
<asp:PlaceHolder ID="ItemTemplatePlaceHolder" runat="server">
</asp:PlaceHolder>
</ItemTemplate>
<SeparatorTemplate>
<tr>
<td colspan="6"><hr /></td>
</tr>
</SeparatorTemplate>
</asp:Repeater>
</asp:Panel>
The code behind: SearchResultControl.ascx.cs
protected void Repeater1_ItemCreated(object sender, RepeaterItemEventArgs e)
{
if (e.Item.DataItem != null)
{
PlaceHolder placeHolder = e.Item.FindControl("ItemTemplatePlaceHolder") as PlaceHolder;
Control searchResultItem = Page.LoadControl("SearchResultItem.ascx");
DataRow row = (e.Item.DataItem as DataRowView).Row;
if (row != null)
{
string diseaseState = row["DiseaseStates"] as string;
searchResultItem.GetType().GetProperty("DiseaseStates").SetValue(searchResultItem, diseaseState, null);
placeHolder.Controls.Add(searchResultItem);
}
}
}
(Full disclosure, I got this idea from this question)
The SetValue calls the DiseaseStates property in SearchResultItem which in turn calls the following method to build the links, set the text, and the events:
private void BuildDiseaseStateLabels(string diseaseStates)
{
PlaceHolder placeHolder = FindControl("DiseaseStatePlaceHolder") as PlaceHolder;
string[] diseaseStateSplit = diseaseStates.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
int count = diseaseStateSplit.Length;
foreach (string diseaseState in diseaseStateSplit)
{
LinkButton d开发者_Python百科iseaseStateLink = new LinkButton();
diseaseStateLink.Text = diseaseState;
//diseaseStateLink.Click += new EventHandler(OnDiseaseStateLinkClick);
diseaseStateLink.CommandArgument = "<%# Eval(\"PatientID\")+ \";\" + Eval(\"PatientStatus\")+ \";\" + Eval(\"Age\")+ \";\" + Eval(\"DiseaseStates\")%>";
diseaseStateLink.CommandName = "OnDiseaseStateLinkClick";
//diseaseStateLink.Command += new CommandEventHandler(OnDiseaseStateLinkClick);
placeHolder.Controls.Add(diseaseStateLink);
if (count != 0)
{
Label splitLabel = new Label();
splitLabel.Text = "|";
placeHolder.Controls.Add(splitLabel);
}
}
}
This is the layout for the SearchResultItem
<div id="SearchResultItemDiv" class="MainSearchResultItem">
<asp:PlaceHolder ID="DiseaseStatePlaceHolder" runat="server">
</asp:PlaceHolder>
</div>
Initially I tried setting the Click
event, but that doesn't work at all. I then set the CommandArgument
and CommandName
but that didn't seem to do the trick. I figured the Command
event might need to be set, but again, no luck. I should note that when a link is clicked the Repeater1_ItemCreated
in SearchResultControl.ascx.cs is called. But since there is no data in e.Item.DataItem
is null and I lose the results.
In one of the questions regarding the same issue, it was suggested that the OnItemCommand
be added, but even that doesn't get called.
I also read A Stumper of an ASP.NET Question and A Stumper of an ASP.NET Question: SOLVED!, to no avail.
What could I possibly be doing wrong? All of the correct event hookups seem there, I'm checking for IsPostBack
and not doing DataBind()
again. blaaargharaggh
Help is always greatly appreciate.
I believe you're running into this issue because the LinkButton
controls are recreated too late in the page lifecycle. You have to remember that when the page is posted back, the control technically does not exist anymore, so the event handler cannot be fired.
If you can recreate the LinkButton
controls somewhere before the Page_Load
event is reached, like OnInit
for example, everything should work fine.
For simple pages the above usually works very well, but there are circumstances where recreating controls during OnInit
requires a lot of overhead, such as storing counters or arrays in ViewState so you can keep track of the controls that need to be recreated after postback. In these situations I would suggest taking a look at the DynamicControlsPlaceHolder
by Denis Bauer. This control is capable of persisting dynamic controls without any addtional code required, which is pretty awesome.
Here's a link to the latest version:
http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx
The problem might be that you're not doing the DataBind()
again.
Because you're building the buttons on the fly, when the page post backs, the buttons haven't been created and are unable to work out which click event it should be firing.
Try getting rid of the IsPostBack
check, so each time the page loads, you're re-build the repeater
.
精彩评论