ASP.NET - Control Events Not Firing Inside Repeate

2020-07-07 04:18发布

问题:

This is a absurdly common issue and having exhausted all of the obvious solutions, I'm hoping SO can offer me some input... I have a UserControl inside a page which contains a repeater housing several controls that cause postback. Trouble is, all of the controls inside of the repeater never hit their event handlers when they postback, but controls outside of the repeater (still in the UC) are correctly handled. I already made sure my controls weren't being regenerated due to a missing if(!IsPostBack) and I verified that Request.Form["__EVENTTARGET"] contained the correct control ID in the Page_Load event. I attempted to reproduce the symptoms in a separate project and it worked as it should.

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="NoteListControl.ascx.cs"
    Inherits="SantekGBS.Web.UserControls.NoteListControl" %>

<asp:UpdatePanel ID="upNotes" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <div class="NoteList" id="divNoteList" runat="server">
            <asp:Repeater ID="repNotes" runat="server">
                <HeaderTemplate>
                    <table width="98%" cellpadding="3" cellspacing="0">
                </HeaderTemplate>
                <ItemTemplate>
                    <tr class="repeaterItemRow">
                        <asp:ImageButton ID="ImageButton1" runat="server" ImageUrl="~/Content/images/DeleteIcon.gif"
                            OnClick="ibRemove_Click" CommandArgument='<%# Container.ItemIndex %>' CommandName='<%# Eval("ID") %>'
                            CausesValidation="false" AlternateText="Delete" />
                        <%# Eval("Text") %></td>
                    </tr>
                </ItemTemplate>
                <FooterTemplate>
                    </table>
                </FooterTemplate>
            </asp:Repeater>
            <asp:PlaceHolder ID="phNoNotes" runat="server" Visible="false">
                <div class="statusMesssage">
                    No notes to display.
                </div>
            </asp:PlaceHolder>
        </div>
    </ContentTemplate>
</asp:UpdatePanel>

public partial class NoteListControl : UserControl
{
    [Ninject.Inject]
    public IUserManager UserManager { get; set; }

    protected List<Note> Notes
    {
        get
        {
            if (ViewState["NoteList"] != null)
                return (List<Note>)ViewState["NoteList"];
            return null;
        }
        set { ViewState["NoteList"] = value; }
    }

    public event EventHandler<NoteEventArgs> NoteAdded;
    public event EventHandler<NoteEventArgs> NoteDeleted;
    public event EventHandler<NoteEventArgs> NoteChanged;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            UtilityManager.FillPriorityListControl(ddlPriority, false);
        }
    }

    protected void ibRemove_Click(object sender, ImageClickEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("ibRemove POSTBACK"); // This is NEVER hit
    }

    public void Fill(List<Note> notes)
    {
        Notes = notes;
        RefreshRepeater();
    }

    private void RefreshRepeater()
    {
        if (Notes != null && Notes.Any())
        {
            var sorted = Notes.OrderByDescending(n => n.Timestamp);
            Notes = new List<Note>();
            Notes.AddRange(sorted);
            repNotes.Visible = true;
            phNoNotes.Visible = false;
            repNotes.DataSource = Notes;
            repNotes.DataBind();
        }
        else
        {
            repNotes.Visible = false;
            phNoNotes.Visible = true;
        }
    }
}

public class NoteEventArgs : EventArgs
{
    public Note Note { get; set; }
    public NoteEventArgs()
    { }
    public NoteEventArgs(Note note)
    {
        this.Note = note;
    }
}

The code is intentionally missing functionality so just disregard that fact.

回答1:

Your edited code has residual CommandArgument and CommandName properties; are you actually handling the Repeater.ItemCommand event?

If so, and if your page calls the control's Fill method on postbacks, that would explain it.

This classic ASP.NET hair-tearing problem is explained in these posts: A Stumper of an ASP.NET Question and A Stumper of an ASP.NET Question: SOLVED!

The explanation is a little mind-bending, but the crux of it is that Repeater.DataBind interferes with ASP.NET's ability to determine which repeater button caused a postback.



回答2:

I found a missing td-tag in the Itemtemplate, sometimes when DOM is incorrect, the updatapanel do strange things.



回答3:

Just about EVERY time I run into this problem it's because DataBind() is being called when it shouldn't be. This will kill most events from controls inside a repeater. I see you have an !IsPostBack check in your Page_Load... so that's a start. But try putting a breakpoint on repNotes.DataBind() and see if it's getting called when you don't expect it.

Does it work OK outside of an UpdatePanel?



回答4:

I ran into the same problem. It happened with me if I've ran the DataBind twice. In other words when I populate the repeater control twice (for any reason) the events wont fire.

I hope that helps.