views:

6181

answers:

4

Hi,

I am adding a LinkButton control dynamically into a PlaceHolder. If I add a new instance of the LinkButton on every OnInit(), then OnClick handler for this LinkButton works.

However, if I store the instance of LinkButton in the session and then add it into collection of controls of the PlaceHolder, LinkButton.OnClick fails to fire.

Is there a way to re-use controls I store in the session in given scenario? Recreating them every time is hardly an option.

Just as a side note - it's an inherited application in 1.1 which I just migrated to 3.5. The 'broken' approach seemed to work in 1.1.

Thanks for all the answers.

public static void Clicked(object sender, EventArgs e) {
    Debugger.Break();
}

protected override void OnPreInit(EventArgs e) {
    base.OnPreInit(e);
    InitLinkButton();
}

private void InitLinkButton() {    
    var lb = new LinkButton();
    plOne.Controls.Add(lb);
    lb.ID = "lb";
    lb.Text = "I will work.";
    lb.Click += Clicked;
    plOne.Controls.Add(lb);

    LinkButton lb2 = null;
    if (Session["lb2"] == null) {
        lb2 = new LinkButton();
        lb2.ID = "lb2";
        lb2.Text = "I won't work.";
        lb2.Click += Clicked;
        Session["lb2"] = lb2;
    } else {
        lb2 = (LinkButton)Session["lb2"];
    }
    plOne.Controls.Add(lb2);
}
+7  A: 

Couple of things:

1) Never, ever, ever store an instance of a WebControl to Session. Every WebControl has a reference to the Page object - which of course references every single other WebControl. As soon as you stash a WebControl into Session, you are basically storing the entire Page and everything it contains. You're on the highway to memory leak city.

2) Every control is recreated on every postback. I think you might be thinking that re-creating your LinkButtons every time is slow, but it's not true.

3) Why isn't recreating your dynamic controls on postback an option? This is what you're supposed to be doing with dynamic controls. The whole idea is that you set up the page the same as it was, so that ViewState can be hooked up to your controls automatically based on their ID's. If you try to add controls to your page dynamically anywhere after Init(), you will not be able to use ViewState to handle your control data, and will have to implement your own mechanism.

My recommendation is to recreate your dynamic controls in Init() - this is the best practice.

womp
Controls in your .aspx are recreated on every postback. Dynamic controls _must_ be recreated on every postback.
Dave Swersky
+1  A: 

you should also check out the dynamic controls placeholder which will help take a lot of the monkey work out of managing your dynamic controls

lomaxx
+1  A: 

It's really a terrible idea to store the LinkButton in session. I can't even imagine the problems that could cause. At the very least, the LinkButton has a reference (by way of the Clicked handler) to the Page - which really shouldn't exist anymore (the Page has been rendered and sent to the client). But, the reference would keep it alive so it won't be GC'ed.

That being said, it's possible that you just need to rewire the Clicked handler:

if (Session["lb2"] == null) {
    /* ... */
} else {
    lb2 = (LinkButton)Session["lb2"];
    lb2.Click += Clicked;
}

Since the LinkButton.Click event is wired to another instance of the Page class (the one that was used before), it's firing would have no visible effect (since that Page was already rendered). Of course, like I said above, this is just utter craziness - so it's not like I've tested this.

If you do use this, then you should also unsubscribe at Page_PreRender or something to avoid the GC problem.

And creating the control again is the normal way to do this - and it's a viable option for everyone else, so you may be overthinking the complications in that.

Mark Brackett
+2  A: 

To answer your question how to get the OnClick to work, you need to connect the event to the method;

lb2.Click += new EventHandler(Clicked);

I just can't see you problem with recreating the control on init, don't overcomplicate things! Enough has been said about what you're storing in your session, so I won't post another answer conserning that issue.

Jesper Karsrud