ASP.NET - 重复器内控件事件未触发

8
这是一个非常常见的问题,我已经尝试了所有明显的解决方案,希望SO能够提供一些帮助... 我在页面中有一个包含多个控件并引发回发的重复器的UserControl。问题是,重复器内的所有控件在回发时都不会触发它们的事件处理程序,但是重复器外部的控件(仍在UC中)被正确处理。我已经确认我的控件没有因为缺少if(!IsPostBack)而被重新生成,并且我验证了Page_Load事件中Request.Form["__EVENTTARGET"]包含正确的控件ID。我试图在另一个项目中重现这些症状,结果却正常。
<%@ 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;
    }
}

这段代码故意缺少一些功能,因此请忽略这一点。

4个回答

4
您编辑的代码中仍存在CommandArgumentCommandName属性;您是否实际处理了Repeater.ItemCommand事件?如果是这样,并且您的页面在回发时调用了控件的Fill方法,那么就可以解释这个问题。
这个经典的ASP.NET问题在这些帖子中有所解释:A Stumper of an ASP.NET QuestionA Stumper of an ASP.NET Question: SOLVED! 解释有点令人费解,但关键在于Repeater.DataBind干扰了ASP.NET确定哪个重复按钮引起回发的能力。

尽管我正在使用CommandArgument和CommandName参数,但我没有通过Repeater.ItemCommand冒泡事件。我使用这些属性来存储信息,在标准按钮单击事件中访问它们。 - Nathan Taylor
我认为链接应该是http://scottonwriting.net/sowBlog/archive/0000/00/00/162929.aspx。 - darasd

3

我发现Itemtemplate中缺少一个td标签,有时候当DOM不正确时,更新面板会出现奇怪的问题。


不错的发现,但实际上你可以忽略它。我展示的标记甚至与生产代码不同。我只是创建了那个<ItemTemplate>来展示效果。所有在ItemTemplate内部的控件都表现得一样。 - Nathan Taylor

3

每次遇到这个问题,几乎都是因为在不应该调用DataBind()的时候调用了它。这会导致大多数重复器内控件的事件失效。我看到你在Page_Load中使用了!IsPostBack检查......这是一个开始。但是请尝试在repNotes.DataBind()上设置断点,看是否在你不希望它被调用时被调用了。

在UpdatePanel之外是否正常工作?


DataBind()方法只在初始页面加载和指定的控件事件之后被调用,但这些事件并没有按照预期触发。UpdatePanel似乎与问题无关。我的应用程序中还有另一个表单,以前也能正常工作,但现在表现出类似的行为,当表单回传时,重复器会像这里一样清空自己。非常奇怪的行为。 - Nathan Taylor
你没有禁用这些控件的ViewState,对吗?你有“另一个表单”……我假设那是一个完全不同的.aspx页面?这个页面上没有额外的表单标签,对吗? - Bryan
Bryan的评论帮了我:在我的情况下,父级重复器上有EnableViewState="false",这阻止了页脚控件的postback处理程序被触发。 - fortboise

1

我遇到了同样的问题。如果我运行DataBind两次,就会发生这种情况。换句话说,当我为重复控件两次填充数据(出于任何原因)时,事件不会触发。

希望这可以帮助你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接