ASP.NET动态添加了LinkBut​​ton - 未调用OnClick处理程序

时间:2009-05-12 23:43:16

标签: asp.net dynamic linkbutton

我正在将一个LinkBut​​ton控件动态添加到PlaceHolder中。如果我在每个OnInit()上添加一个新的LinkBut​​ton实例,那么此LinkBut​​ton的OnClick处理程序就可以工作。

但是,如果我将LinkBut​​ton的实例存储在会话中,然后将其添加到PlaceHolder的控件集合中,则LinkBut​​ton.OnClick将无法触发。

有没有办法在给定方案中重用我在会话中存储的控件?每次重新创建它们都不是一种选择。

正如旁注 - 它是1.1中的继承应用程序,我刚刚迁移到3.5。 “破碎”的方法似乎适用于1.1。

感谢所有答案。

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

4 个答案:

答案 0 :(得分:10)

一些事情:

1)永远不要将WebControl的实例存储到Session。每个WebControl都有一个对象的引用 - 当然它引用了每一个其他的WebControl。只要将WebControl存储到Session中,就基本上存储整个页面及其包含的所有内容。你正在通往内存泄漏城市的高速公路上。

2)每次回发都会重新创建每个控件。我想你可能会认为每次重新创建你的LinkBut​​tons都很慢,但事实并非如此。

3)为什么不在回发选项上重新创建动态控件?这就是你应该用动态控件做的事情。整个想法是您将页面设置为与原来相同,以便ViewState可以根据其ID自动连接到您的控件。如果您尝试在Init()之后的任何位置动态地向页面添加控件,您将无法使用ViewState来处理控件数据,并且必须实现自己的机制。

我的建议是在Init()中重新创建动态控件 - 这是最好的做法。

答案 1 :(得分:3)

要回答您的问题如何让OnClick正常工作,您需要将事件连接到方法;

lb2.Click += new EventHandler(Clicked);

我只是看不到你在init上重新创建控件的问题,不要过于复杂化!关于你在会话中存储的内容已经足够了,所以我不会发布另一个回答这个问题的答案。

答案 2 :(得分:1)

你还应该查看dynamic controls placeholder,这将有助于减少管理动态控件的猴子工作

答案 3 :(得分:1)

将LinkBut​​ton存储在会话中真是个糟糕的主意。我甚至无法想象可能导致的问题。至少,LinkBut​​ton有一个引用(通过Clicked处理程序)到页面 - 它实际上不应该存在(页面已被渲染并发送到客户端)。但是,引用会使它保持活着,因此它不会被GC控制。

话虽如此,可能你需要重新连接Clicked处理程序:

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

由于LinkBut​​ton.Click事件连接到Page类的另一个实例(之前使用过的那个),因此它的触发将没有可见效果(因为该页面已经呈现)。当然,就像我上面所说的那样,这只是一种疯狂 - 所以它并不像我测试过的那样。

如果您确实使用了这个,那么您还应该取消订阅Page_PreRender或其他东西以避免GC问题。

再次创建控件是正常的做法 - 对于其他人来说这是一个可行的选择,所以你可能会过度思考其中的复杂情况。