2

我正在将 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

4 回答 4

10

几件事:

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

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

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

我的建议是在 Init() 中重新创建动态控件——这是最佳实践。

于 2009-05-12T23:53:10.720 回答
3

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

lb2.Click += new EventHandler(Clicked);

我只是看不到您在 init 上重新创建控件的问题,不要使事情过于复杂!关于您在会话中存储的内容已经说得够多了,所以我不会发布关于该问题的另一个答案。

于 2009-05-13T00:05:03.383 回答
1

您还应该检查动态控件占位符,这将有助于减少管理动态控件的大量工作

于 2009-05-12T23:57:23.910 回答
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 已经呈现)。当然,就像我上面说的,这完全是疯狂的——所以我没有测试过这个。

如果您确实使用它,那么您还应该在 Page_PreRender 或其他地方取消订阅以避免 GC 问题。

再次创建控件是执行此操作的正常方法 - 它对其他人来说是一个可行的选择,因此您可能会过度考虑其中的复杂性。

于 2009-05-12T23:58:11.647 回答