【问题标题】:ASP.NET - Control Events Not Firing Inside RepeaterASP.NET - 控制事件不在中继器内触发
【发布时间】:2009-11-23 20:34:43
【问题描述】:

这是一个荒谬的常见问题,并且已经用尽了所有明显的解决方案,我希望 SO 可以为我提供一些输入...我在页面中有一个 UserControl,其中包含一个转发器,其中包含多个导致回发的控件。问题是,转发器内部的所有控件在回发时都不会触发它们的事件处理程序,但是转发器外部的控件(仍在 UC 中)得到了正确处理。我已经确保由于缺少 if(!IsPostBack) 而没有重新生成我的控件,并且我验证了 Request.Form["__EVENTTARGET"] 在 Page_Load 事件中包含正确的控件 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;
    }
}

代码故意缺少功能,因此请忽略这一事实。

【问题讨论】:

    标签: asp.net events user-controls postback


    【解决方案1】:

    您编辑的代码有剩余的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 冒泡事件。我正在使用属性来存储我在标准按钮单击事件中访问的信息。
    【解决方案2】:

    我在Itemtemplate中发现了一个缺失的td-tag,有时当DOM不正确时,updatapanel会做一些奇怪的事情。

    【讨论】:

    • 不错,但您实际上可以忽略这一点。我显示的标记甚至与生产代码不同。我创建 只是为了显示效果。 ItemTemplate 中的所有控件的行为方式都相同。
    【解决方案3】:

    几乎每次我遇到这个问题都是因为 DataBind() 在不应该被调用的时候被调用。这将杀死转发器内控件的大多数事件。我看到您的 Page_Load 中有一个 !IsPostBack 检查...所以这是一个开始。但是尝试在 repNotes.DataBind() 上放置一个断点,看看它是否在你不期望的时候被调用。

    在 UpdatePanel 之外可以正常工作吗?

    【讨论】:

    • DataBind() 仅在初始页面加载时和指定的控制事件之后被调用 - 这些事件都没有按应有的方式被触发。 UpdatePanel 似乎与该问题无关。我的应用程序中有另一个表单,它也曾经工作过,它也表现出类似的行为,当表单发回转发器时,它会像这里一样清空自己。非常奇怪的行为。
    • 您没有为这些控件中的任何一个禁用 ViewState 对吧?你有“另一种形式”......我认为那是一个完全不同的 .aspx 页面?您在此页面中没有额外的表单标签?
    • Bryan 的评论帮助了我:在我的例子中,我在父转发器上有 EnableViewState="false",这阻止了页脚控件的回发处理程序被触发。
    【解决方案4】:

    我遇到了同样的问题。如果我运行 DataBind 两次,它就会发生在我身上。换句话说,当我(出于任何原因)填充中继器控件两次时,事件不会触发。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-20
      • 1970-01-01
      • 2018-11-18
      • 2019-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多