ASP.NET dynamic Command Button event not firing

匿名 (未验证) 提交于 2019-12-03 02:14:01

问题:

I'm trying to create Command Buttons dynamically, but clicking the button in question doesn't seem to raise the corresponding CommandButton_Click event. I noticed that in the examples on SO a property is set for Button.OnCommand as well as the CommandName and CommandArgument but it isn't an option in intellisense.

So the question is, what am I doing wrong here (code below without the OnCommand), is it accessed in some other way - if so, why do the examples I've found all show it as .OnCommand?

EDIT: Further to help, I have added the handler however the event is still not firing. The buttons reside in an UpdatePanel and are rebuilt on every postback (along with the handler). I have created a simplified example of what I'm doing which is shown below If the button event fires, it writes "EVENT FIRED" to the txtTestFired Textbox - suffice to say I have never seen that. This is really driving me nuts, any help is very gratefully received.

.aspx file

<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 file

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 

回答1:

Essentially you need to create the original controls once on page load in order to be able to handle the button click, you then need to clear the controls and re-generate them either in the button click handler or as you have done on pre-render - i think it is cleaner on the click handler, so you need the same code in both (preferable refactored out to a separate method)

The example below would mean minimum code changes for you:

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:

You have to wire it up like this (in C#):

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

Alternatively you can inject the attribute --> onclick = "Button_Clicked" like this:

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

If you want it in VB.NET go to this page and knock yourself out - I could do it for you but what's the point :)

EDIT: keep in mind you'll have to re-wire the event-handler (as shown above) every page-load.

EDIT: OK - I see the problem now that you added the rest of the code. You are wiring up the event handler on pre_render. Event handlers are executed just before load_complete, which happens before pre_render. This is why you event_handler doesn't execute: you're adding it too late in the page lifecycle. Put that code in the page_load routine and it should work.



回答3:

I had this same problem, I was loading the controls just fine. the events were firing the first time, but not the second time. The problem was I didn't have a unique identifier tied to the controls. So I added a unique ID field to the control I was adding to the page, and it worked just fine, every click.



回答4:

You need to wire up the click event. See this code...

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 

Hope this helps...



回答5:

Correct way is:

  1. OnLoad - generate dynamic content (create dynamic buttons)
  2. Button OnClick - consume event and regenerate correct content

But it requires to generate content twice - once for create buttons to process events and then erase old content and generate correct one - second time. You can workaround it like this:

  1. OnLoad - check if buton was clicked
  2. PreRender - generate correct content with dynamic buttons (content is generated only once)

My example to do that:

<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" /> 

And in code:

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; } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!