ASP.NET Dynamically added LinkButton - OnClick handler is not being called

Art picture Art · May 13, 2009 · Viewed 25.9k times · Source

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

Answer

womp picture womp · May 13, 2009

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.