在Repeater或GridView中第一次单击时,ItemCommand不会触发

这让我疯狂了2天 – 希望有人见过这个。

我有这个问题,在转发器或网格视图中第一次单击控件无法触发ItemCommand事件,所有后续点击工作。 控件被加载到Base.aspx上的占位符中,就像这样

private void LoadUserControl() { string controlPath = LastLoadedControl; if (!string.IsNullOrEmpty(controlPath)) { ph.Controls.Clear(); UserControl uc = (UserControl)LoadControl(controlPath); ph.Controls.Add(uc); } } 

我想知道这是一个viewstate问题,以及我应该使用DataBind()在哪些页面事件中。 我在不同的页面事件中尝试了数据绑定,在页面和控件上启用了视图状态而没有结果的变化。

这是GridView模板,但我对转发器控件也有相同的行为,所以我不相信它的控制就是这个问题。

  <asp:RadioButton ID="rbEnable" GroupName="MyGroup" runat="server" Text="Enabled" Checked="" /> <asp:RadioButton ID="rbDisable" runat="server" GroupName="MyGroup" Text="Disabled" Checked="" /> <asp:Button ID="btnEnable" runat="server" CommandArgument="" CommandName="Enable" ToolTip="Enable" Text="Save" /> <asp:Button ID="btnDisable" runat="server" CommandArgument="" Visible="false" CommandName="Disable" ToolTip="Disable" Text="Disable" />  

一些可能相关的进一步信息:

我注意到的是在usercontrol的Page_Load事件中,我正在重新绑定控件。 这可能是控制状态被重写的原因,但如果我在ascx中向此区域添加if(!IsPostback),则此代码部分根本不会像在aspx页面上那样触发。 这将是我认为重新控制控制的正确部分。

MikeW,
经过几个小时的摆弄,我找到了问题的根源。
它与转发器或gridview没有任何关系。
它只是一个动态控制回发问题。

要解决您的问题:
令人惊讶的是,您的代码中只缺少一行。
在加载控件时,将其分配给其ID,如下所示:

 UserControl uc = (UserControl)LoadControl(controlPath); uc.ID = "mycontrol"; ph.Controls.Add(uc); 

这样,当你回发时,页面知道哪个控件是哪个。

为了更容易解释这一点,让我们简化问题。
这是一个连续两次单击按钮动态创建另一个按钮的方案:

  • 单击一个按钮Button1,单击该按钮将动态加载另一个按钮Button2。 假设Button2的动作与显示当前时间一样简单。
  • 现在,单击Button1。
  • 要保留Button2,您必须利用ViewState告诉页面有动态控件。 像你一样,我们可以记住控件的路径或类的名称。
  • 当页面回发时,在Page_Load ,我们查看ViewState以查看我们正在尝试保留的控件,因此我们将其加载到那里(这相当于上面的LoadUserControl()函数)。
  • 到目前为止,Button2是可见的,点击后,它会很好地完成它的动作。
  • 不要单击Button2,只需再次单击Button1(这相当于在两个不同的动态控件之间切换的情况)。
  • 猜猜现在发生了什么: Page_Load将从ViewState加载Button2。 在清除占位符后,Button1的Click事件将加载另一个Button2实例。
  • 由于你没有给它分配一个ID,它会在UniqueID自己分配一个,而那两个Button2将有类似ctl02ctl03的东西。
  • 现在单击Button2。
  • 你会说“那很好,我们会覆盖旧的”。 是的,但不是没有身份证。
  • 由于您没有在回发中为其标识它,因此它将使用按顺序生成的UniqueID
  • 现在该页面正在寻找不存在的ctl03 ,因此Click不会触发。
  • 但是,到目前为止,我们有一个全新的Button2,带有UniqueID ctl02
  • 单击这个新的Button2将工作得很好,因为它是唯一的Button2,所以它恰好具有ctl02UniqueID

那么,如何分配ID使它工作?
这样,生成的每个新控件都将具有相同的ID,因此在回发时,它可以找到它正在查找的内容,无论是在Page_Load中生成还是在另一个按钮的Click事件中生成。

希望这能解释它为什么会起作用,但就你所关心而言,只需为它分配一个ID就可以了。
我认为分享它背后的机制以及为什么会是这种情况会很有趣。 =)

我想通了,但我不明白为什么。
原始代码是:

 Me.rpAgreementContractors.DataSource = dtContractors Me.rpAgreementContractors.DataBind() Me.tblAgreementContractors.Visible = True Me.phDataPane.Controls.Add(Me.tblAgreementContractors) 

在设置数据源并绑定它之前,我更改了它以使表可见并将其添加到占位符。 问题解决了。

 Me.tblAgreementContractors.Visible = True Me.phDataPane.Controls.Add(Me.tblAgreementContractors) Me.rpAgreementContractors.DataSource = dtContractors Me.rpAgreementContractors.DataBind() 

我不确定你的其余代码,但通常当我看到“第一个动作行为与后续动作不同”的问题时,这是因为我在IsPostBack部分的错误一侧放置了一些东西。

例如,我发现自己在回发时会发生绑定,因此我的事件在第二次回发之前不起作用,因为第一次回发是在他们出生时,并且初始页面加载从未做过那部分。

我认为你走在正确的轨道上; 确保您在适当的时刻绑定并布线您的活动。