简体   繁体   中英

Dynamically created button after page load realoads the page but does not fire the

I have a problem with asp.net event system.

As the page is being loaded for the first time, a DropDownList is being populated and that's it. On the list SelectedIndexChange the page does a page postback and loads some more info, dynamically creating buttons for it based on some data taken out from the DB.

And at this point all works as expected, the CustomDivs are created and displayed correctly. The problems happens when i click on one of the dynamically created buttons, the page does the postback, goes trouhg the page load but never enters the method of the button that was clicked.

Looking around in the internet i read something about event handlers must be created in the Page_Load method to registered. So i even modified the code behind so that the CaricaPostazioni() method would be fired in the Page_Load, but that did not work. I also tried some other stuff like AutoPostBack property or UseSubmitBheaviour or CausesValidation but nothing seems to work as expected.

I should say that this page is a content page of master page that does absolutely nothing in it's Page_Load()

Any one can help me in this matter? Thank you very much!

Here is the code behind of assegnapostazione.aspx



    using Industry4_camerana_gruppo1.App_Code;
    using Industry4_camerana_gruppo1.App_Code.Dao;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    namespace Industry4_camerana_gruppo1 {

        public partial class assegnapostazione : System.Web.UI.Page {

            static List Macchinisti = null;

            protected void Page_Load(object sender, EventArgs e) {

                if (Macchinisti == null) {
                    Macchinisti = new daoUtente().GetByRuolo("macchinista");

                    drp_Macchinisti.Items.Add(new ListItem("Seleziona...", "-1"));
                    foreach (Utente U in Macchinisti) {
                        drp_Macchinisti.Items.Add(new ListItem(U.Username, U.ID.ToString()));
                    }

                }

            }

            public void CaricaPostazioni() {

                //if (drp_Macchinisti.SelectedValue == "-1") return;

                int IDUtente = Convert.ToInt32(drp_Macchinisti.SelectedItem.Value);

                List Postazioni = new daoPostazioni().GetAll();
                Dictionary Relazioni = new daoPostazioni().GetUtentePostazioni(IDUtente);

                if (Postazioni != null) {
                    Panel row = new Panel();
                    row.CssClass = "row";
                    int i = 0;
                    foreach (Postazione p in Postazioni) {
                        if (i % 4 == 0) {
                            pnl_Postazioni.Controls.Add(row);
                            row = new Panel();
                            row.CssClass = "row";
                        }
                        if (Relazioni.ContainsKey(p.ID)) {
                            row.Controls.Add(CustomDiv(p, IDUtente, true));
                        } else {
                            row.Controls.Add(CustomDiv(p, IDUtente, false));
                        }
                        i++;
                    }
                    pnl_Postazioni.Controls.Add(row);
                }

            }

            public Panel CustomDiv(Postazione P, int IDUtente, bool Assegnato) {

                //  
                //        
                //            
                //            
                //                Foratura
                //            
                //        
                //    

                Panel wrapper = new Panel();
                wrapper.CssClass = "col";

                Panel card = new Panel();
                card.CssClass = "card text-center postazione form-group";

                Image img = new Image();
                img.CssClass = "mx-auto d-block width-70";
                img.ID = "btn_" + P.ID;
                img.ImageUrl = "~/imgs/ic" + P.Tipo + ".png";

                Panel cardTitle = new Panel();
                cardTitle.CssClass = "card-title";

                Label title = new Label();
                title.Text = P.Tipo.ToUpper() + " - " + P.Tag;

                Button btn = new Button();
                //btn.ID = "btn_" + P.ID + IDUtente;
                btn.Attributes.Add("PID", P.ID.ToString());
                btn.Attributes.Add("UID", IDUtente.ToString());
                //btn.UseSubmitBehavior = true;
                if (Assegnato) {
                    btn.Click += new EventHandler(btn_Rimuovi_Click);
                    //btn.Click += delegate {
                    //    btn_Rimuovi_Click(btn, null);
                    //};
                    btn.CssClass = "btn btn-warning mx-auto form-control";
                    btn.Text = "Rimuovi";
                } else {
                    btn.Click += new EventHandler(btn_Assegna_Click);
                    //btn.Click += delegate {
                    //    btn_Assegna_Click(btn, null);
                    //};
                    btn.CssClass = "btn btn-success mx-auto form-control";
                    btn.Text = "Assegna";
                }

                card.Controls.Add(img);
                cardTitle.Controls.Add(title);
                card.Controls.Add(cardTitle);
                card.Controls.Add(btn);
                wrapper.Controls.Add(card);

                return wrapper;

            }

            protected void drp_Macchinisti_SelectedIndexChanged(object sender, EventArgs e) {
                CaricaPostazioni();
            }

            protected void btn_Rimuovi_Click(object sender, EventArgs e) {
                Button btn = (Button)sender;
                new daoPostazioni().AddRelazione(Convert.ToInt32(btn.Attributes["UID"]), Convert.ToInt32(btn.Attributes["PID"]));
            }

            protected void btn_Assegna_Click(object sender, EventArgs e) {
                Button btn = (Button)sender;
                new daoPostazioni().DeleteRelazione(Convert.ToInt32(btn.Attributes["UID"]), Convert.ToInt32(btn.Attributes["PID"]));
            }

        }

    }

Well, I have an answer for you but I don't think you are going to like it.

Due to the stateless nature of webforms, any controls that you add dynamically to a form on a postback will also need to be added back to the page and have it's server events rebound during the OnInit event.

I've created a minimal example that can demonstrate what's going on with this behavior so you can better understand what's happened.

ButtonTest.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ButtonTest.aspx.cs" Inherits="ButtonTest.ButtonTest" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form runat="server">
        <asp:Panel runat="server" ID="ButtonPanel">
            <asp:Button runat="server" ID="ButtonAdd" OnClick="ButtonAddClick" Text="Click Me"></asp:Button>
        </asp:Panel>
    </form>
</body>
</html>

And the code behind:

ButtonTest.aspx.cs

using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;

namespace ButtonTest
{
    public partial class ButtonTest : System.Web.UI.Page
    {
        static List<Button> buttons = new List<Button>();
        static bool allowItToWork = true;
        protected override void OnInit(EventArgs e)
        {
            if(Page.IsPostBack && allowItToWork)
            {
                foreach (var button in buttons)
                {
                    button.Click += ButtonAddClick; // Comment me out and added button's will do nothing when clicked.
                    ButtonPanel.Controls.Add(button);
                }
            }
        }

        protected void ButtonAddClick(object sender, EventArgs e)
        {
            var button = new Button();
            button.Click += ButtonAddClick;
            button.Text = "Click Me Too";
            buttons.Add(button);
            ButtonPanel.Controls.Add(button);
        }
    }
}

You can toggle between desirable and undesirable behavior by changing the value of the allowItToWork boolean.

When it's set to true, the OnInit overload is adding all buttons back onto the page, as well as applying their event handlers again, because those handlers seem to be lost during the PostBack (unsure on why this happens.) You can click away and new buttons will be added onto the form forever and ever.

When it's set to false, the added button will appear whenever you click the initial button, but it won't fire an event handler as it's no longer bound, and clicking the original button repeatably won't continue to add additional buttons, you'll only ever see a single one, and that one will disappear on PostBack if clicked.

So, the end result of this is essentially that you're stuck reconstructing the whole shebang in the OnInit event.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM