Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create buttons and hook up events from postback

I need to generate buttons initially based on quite a processor and disk intensive search. Each button will represent a selection and trigger a postback. My issue is that the postback does not trigger the command b_Command. I guess because the original buttons have not been re-created. I cannot affort to execute the original search in the postback to re-create the buttons so I would like to generate the required button from the postback info.

How and where shoud I be doing this? Should I be doing it before Page_Load for example? How can I re-construct the CommandEventHandler from the postback - if at all?

   namespace CloudNavigation
{
    public partial class Test : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (IsPostBack)
            {
                // how can I re-generate the button and hook up the event here
                // without executing heavy search 1
            }
            else
            {
                // Execute heavy search 1 to generate buttons
                Button b = new Button();
                b.Text = "Selection 1";
                b.Command += new CommandEventHandler(b_Command);
                Panel1.Controls.Add(b);
            }
        }

        void b_Command(object sender, CommandEventArgs e)
        {
            // Execute heavy search 2 to generate new buttons
            Button b2 = new Button();
            b2.Text = "Selection 2";
            b2.Command += new CommandEventHandler(b_Command);
            Panel1.Controls.Add(b2);
        }
    }
}
like image 803
dice Avatar asked Nov 07 '08 17:11

dice


2 Answers

The b_Command Event Handler method is not being executed because on post back buttons are not being recreated (since they are dynamically generated). You need to re-create them every time your page gets recreated but in order to do this you need to explicitly cache information somewhere in state.

If this a page-scoped operation easiest way is to store it in the ViewState (as strings - if you start loading the ViewState with objects you'll see performance go down) so that you can check it on next load (or any other previous event) and re-create buttons when reloading the page. If the operation is session-scoped, you can easily store an object (array or whatever) in session and retrieve it on next Load (or Init) to re-create your controls.

This scenario means that you need just to store some info about your button in your b_Command EventHandler instead of creating and adding buttons since if you do so you'll lose relative information in the next postback (as it is happening now).

so your code would become something like:

namespace CloudNavigation
{
    public partial class Test : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (IsPostBack)
            {
                this.recreateButtons();
            }
            else
            {
                // Execute heavy search 1 to generate buttons
                Button b = new Button();
                b.Text = "Selection 1";
                b.Command += new CommandEventHandler(b_Command);
                Panel1.Controls.Add(b);
                //store this stuff in ViewState for the very first time
            }
        }

        void b_Command(object sender, CommandEventArgs e)
        {
            //Execute heavy search 2 to generate new buttons
            //TODO: store data into ViewState or Session
            //and maybe create some new buttons
        }

        void recreateButtons()
        {
            //retrieve data from ViewState or Session and create all the buttons
            //wiring them up to eventHandler
        }
    }
}

If you don't want to call recreateButtons on page load you can do it on PreLoad or on Init events, I don't see a difference since you'll be able to access ViewState/Session variables everywhere (on Init viewstate is not applied but you can access it to re-create your dynamic buttons).

Someone will hate this solution but as far as I know the only way to retain state data server-side is ViewState - Session - Page.Transfer or client-side cookies.

like image 124
JohnIdol Avatar answered Sep 19 '22 11:09

JohnIdol


The buttons need to be created before the load event, or state won't be wired up correctly. Re-create your buttons in Init() instead.

As for how to do this without re-running the search, I suggest you cache the results somewhere. The existence of a result set in the cache is how your button code in the Init() event will know it needs to run.

Alternatively, you could place the buttons on the page statically. Just put enough there to handle whatever the search returns. If you're thinking that maybe that would be way too many items, then ask your self this: will your users really want to sort through that many items? Maybe you should consider paging this data, in which case static buttons aren't as big a deal any more.

like image 22
Joel Coehoorn Avatar answered Sep 22 '22 11:09

Joel Coehoorn