ASP.NET动态命令按钮事件未触发

时间:2009-11-21 15:34:13

标签: asp.net vb.net webforms button

我正在尝试动态创建命令按钮,但是单击有问题的按钮似乎没有引发相应的CommandButton_Click事件。我注意到在SO的示例中,为Button.OnCommand以及CommandName和CommandArgument设置了属性,但它不是intellisense中的选项。

所以问题是,我在这里做错了什么(没有OnCommand的代码),是否以其他方式访问 - 如果是这样,为什么我发现的例子都显示为.OnCommand?

编辑:为了提供帮助,我添加了处理程序,但事件仍未触发。这些按钮位于UpdatePanel中,并在每次回发时重建(与处理程序一起)。我创建了一个简化的例子,我正在做的事情如下所示:如果按钮事件触发,它会将“EVENT FIRED”写入txtTestFired文本框 - 足以说我从未见过它。这真让我疯了,非常感谢任何帮助。

.aspx文件

<form id="frmMain" runat="server">
    <asp:ScriptManager ID="scmAddProducts" runat="server">
    </asp:ScriptManager>
    <asp:updatepanel runat="server">
        <ContentTemplate>
            <asp:TextBox ID="txtProduct" runat="server"></asp:TextBox>
            <br />
            <asp:Button ID="btnAddItem" runat="server" Text="Add Line" />&nbsp;
            <asp:TextBox ID="txtTestFired" runat="server"></asp:TextBox>
            <br />
            <br />
            <asp:Panel ID="pnlAddedLines" runat="server"></asp:Panel>
        </ContentTemplate>
    </asp:updatepanel>
</form>

.aspx.vb文件

Protected Sub btnAddItem_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnAddItem.Click
    Dim dtItems As New System.Data.DataTable

    If Session("Items") Is Nothing Then
        Dim dcColumn As New System.Data.DataColumn
        dcColumn.DataType = Type.GetType("System.String")
        dcColumn.ColumnName = "Product"
        dtItems.Columns.Add(dcColumn)
        Session("Items") = dtItems
    End If

    dtItems = CType(Session("Items"), System.Data.DataTable)
    Dim drRow As System.Data.DataRow
    drRow = dtItems.NewRow()
    drRow("Product") = txtProduct.Text
    dtItems.Rows.Add(drRow)

    Session("Items") = dtItems
    txtProduct.Text = ""
End Sub
Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
    If Not Session("Items") Is Nothing Then
        Dim dtItems As System.Data.DataTable = CType(Session("Items"), System.Data.DataTable)
        Dim iItemIndex As Integer = 1
        For Each drRow In dtItems.Rows
            Dim btnClose As New Button
            btnClose.ID = "btnClose" & iItemIndex
            btnClose.CssClass = "formCloseButton"
            btnClose.Text = "X"
            AddHandler btnClose.Click, AddressOf Button_Clicked
            pnlAddedLines.Controls.Add(btnClose)
            btnClose = Nothing

            Dim txtProduct = New TextBox
            txtProduct.ID = "txtProduct" & iItemIndex
            txtProduct.CssClass = "formText"
            txtProduct.Text = drRow("Product")
            txtProduct.Columns = "40"
            pnlAddedLines.Controls.Add(txtProduct)
            iItemIndex += 1

            Dim litHR = New Literal
            litHR.Text = "<hr />"
            pnlAddedLines.Controls.Add(litHR)
            litHR = Nothing
        Next
    End If
End Sub
Private Sub Button_Clicked(ByVal sender As Object, ByVal e As System.EventArgs)
    txtTestFired.Text = "EVENT FIRED"
End Sub

5 个答案:

答案 0 :(得分:6)

你必须像这样连接它(在C#中):

myButton.Click += new EventHandler(this.Button_Clicked);

或者你可以注入属性 - &gt; onclick = "Button_Clicked"喜欢这样:

myButton.Attributes.Add("onclick", "Button_Clicked");

如果你想在VB.NET中使用to this page并将自己敲掉 - 我可以为你做,但重点是:)

编辑:请记住,每次页面加载时都必须重新连接事件处理程序(如上所示)。

编辑:好的 - 我现在看到问题是您添加了其余代码。您正在pre_render上连接事件处理程序。事件处理程序在load_complete之前执行,这发生在pre_render之前。这就是你event_handler没有执行的原因:你在页面生命周期中添加它太晚了。将该代码放在page_load例程中,它应该可以正常工作。

答案 1 :(得分:4)

基本上,您需要在页面加载时创建一次原始控件,以便能够处理按钮单击,然后您需要清除控件并在按钮单击处理程序中重新生成它们或者您已经完成预渲染 - 我认为它在Click处理程序上更干净,所以你需要两个相同的代码(最好是重构为单独的方法)

以下示例意味着您需要进行最少的代码更改:

Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
    If Not Session("Items") Is Nothing Then
        pnlAddedLines.Controls.Clear()
        GenerateControls()
    End If
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    If Not Session("Items") Is Nothing Then
        GenerateControls()
    End If
End Sub
Private Sub GenerateControls()
    Dim dtItems As System.Data.DataTable = CType(Session("Items"), System.Data.DataTable)
    Dim iItemIndex As Integer = 1
    For Each drRow In dtItems.Rows
        Dim btnClose As New Button
        btnClose.ID = "btnClose" & iItemIndex

答案 2 :(得分:1)

我有同样的问题,我正在加载控件就好了。事件是第一次发射,但不是第二次发射。问题是我没有绑定控件的唯一标识符。所以我在我添加到页面的控件中添加了一个唯一的ID字段,每次点击都很好。

答案 3 :(得分:0)

您需要连接点击事件。看到这段代码......

Partial Class _Default
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        Dim button1 As New Button
        Dim button2 As New Button

        button1.ID = "button1"
        button1.Text = "Button 1"
        button2.ID = "button2"
        button2.Text = "Button 2"

        AddHandler button1.Click, AddressOf OnClick
        AddHandler button2.Click, AddressOf OnClick

        form1.Controls.Add(button1)
        form1.Controls.Add(button2)

    End Sub

    Private Sub OnClick(ByVal sender As Object, ByVal e As System.EventArgs)

        Dim buttonId As String

        buttonId = DirectCast(sender, Button).ID

        Response.Write("Button clicked: " + buttonId)

    End Sub

End Class

希望这会有所帮助......

答案 4 :(得分:0)

正确的方法是:

  1. OnLoad - 生成动态内容(创建动态按钮)
  2. 按钮OnClick - 消耗事件并重新生成正确的内容
  3. 但它需要生成两次内容 - 一次用于创建按钮来处理事件,然后删除旧内容并生成正确的一秒钟。您可以像这样解决它:

    1. OnLoad - 检查是否点击了按钮
    2. PreRender - 使用动态按钮生成正确的内容(内容仅生成一次)
    3. 我这样做的例子:

      <script type="text/javascript" language="javascript">
          function SetPostBackAction(Action,ReturnValue)
          {
              if(ReturnValue)
                  document.getElementById('<%=hfPostBackAction.ClientID%>').value=Action;
              return ReturnValue;
          }
      </script>
      <asp:HiddenField ID="hfPostBackAction" EnableViewState="false" runat="server" />
      

      在代码中:

      protected void Page_PreRender(object sender, EventArgs e)
      {
          //Dynamic button in PreRender
          System.Web.UI.WebControls.Button btn=new System.Web.UI.WebControls.Button()
          btn.ID=string.Format("DeleteButton_SomeData{0}", 12345);
          btn.Text="Delete";
          btn.OnClientClick=string.Format("return SetPostBackAction('DeleteButton_SomeData{0}',window.confirm('Are you sure to delete?'))", 12345);
          btn.Click+=new EventHandler(btnDelete_Click);//This method will not be called if button is created in PreRender
      }
      
      protected void Page_Load(object sender, EventArgs e)
      {
          //Do something...
          //Check Action
          ProccessAction();//You can check action whereever you want
      }
      
      protected void ProccessAction()
      {
          string Action=Request.Form[hfPostBackAction.UniqueID]??string.Empty;
          int SomeData;
      
          if(Action.StartsWith("DeleteButton_"))//Is action?
          {
              SomeData=int.Parse(Action.Substring("DeleteButton_SomeData".Length));
              //Do something...
          }
          //Erase Action field not to fire action next time accidentially
          hfPostBackAction.Value=string.Empty;
      }