【问题标题】:ASP.NET Dynamically added LinkButton - OnClick handler is not being calledASP.NET 动态添加的 LinkBut​​ton - 未调用 OnClick 处理程序
【发布时间】:2010-02-12 09:35:36
【问题描述】:

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

【问题讨论】:

    标签: asp.net dynamic linkbutton


    【解决方案1】:

    几件事:

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

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

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

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

    【讨论】:

    • 每次回发时都会重新创建 .aspx 中的控件。动态控件必须在每次回发时重新创建。
    【解决方案2】:

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

    lb2.Click += new EventHandler(Clicked);
    

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        在会话中存储 LinkBut​​ton 真是个糟糕的主意。我什至无法想象可能导致的问题。至少,LinkBut​​ton 有一个对页面的引用(通过 Clicked 处理程序)——它真的不应该再存在了(页面已经被渲染并发送到客户端)。但是,引用会使其保持活动状态,因此不会被 GC'ed。

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

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

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

        如果你确实使用了这个,那么你也应该在 Page_PreRender 或其他地方取消订阅以避免 GC 问题。

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

        【讨论】:

          猜你喜欢
          • 2020-12-26
          • 2010-09-12
          • 1970-01-01
          • 1970-01-01
          • 2016-08-17
          • 2011-01-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多