开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜