代码之家  ›  专栏  ›  技术社区  ›  Hugo Migneron

使用事件处理程序动态加载用户控件-注销

  •  5
  • Hugo Migneron  · 技术社区  · 14 年前

    我有一个带有面板的窗体,在该窗体上动态加载多个用户控件。我为每个控件处理事件。

    UserControl userControl1 = LoadControl("control.ascx") as UserControl;
    userControl1.Event += new ControlEventHandler(userControl_Event);
    this.Panel.Controls.Add(userControl1);
    
    UserControl userControl2 = LoadControl("control.ascx") as UserControl;
    userControl2.Event += new ControlEventHandler(userControl_Event);
    this.Panel.Controls.Add(userControl2);
    
    ...
    

    现在当我去掉面板上的控件时,我只需要做一个

    this.Panel.Controls.Clear();
    

    Clear()函数负责清除事件吗?还是我应该这样做

    foreach(Control control in this.Panel.Controls)
    {
        UserControl userControl = control as UserControl;
        if(userControl != null)
        {
            userControl -= userControl_Event;
        }
    }
    

    在我清除面板内容之前?

    基本上,我正在寻找一种方法来动态加载用户控件并处理它们的事件,而不在清除它们时造成泄漏。

    谢谢!

    编辑: 因为我的控件是在页面的Page\u Init事件中创建的(每次都是动态加载的),所以说它们的寿命不能长于页面的寿命是正确的吗? 据我所知,该控件不存在后,一个职位回来。每次都会创建一个新的。因此,我不必注销事件,因为它的对象在下一个页面加载时甚至不存在。对吗?

    5 回复  |  直到 14 年前
        1
  •  5
  •   Jason Coyne    14 年前

    即使在清除了集合之后,该页仍将保存对动态实例化控件的引用,这将阻止控件被收集,直到该页本身被收集为止。

    但是,如果这是一个windows窗体应用程序,那么在窗体被释放之前,内存将被有效地泄漏。

        2
  •  2
  •   Leniel Maccaferri    14 年前

    MSDN上的此页回答了您的问题:

    Control..::.ControlCollection..::.Clear Method

    引用它:

    重要

    调用Clear方法不会 必须显式调用Dispose 避免内存泄漏的方法。

        3
  •  0
  •   Tim Mahy    14 年前

        4
  •  0
  •   orka    14 年前

    正确的说法是,动态加载的usercontrols的寿命不能超过其所属页面的寿命。但是,如果从页面控件集合中删除web控件并将其分配给会话变量(例如,session变量)可能会导致web控件的寿命比页面长,则我们不能说这是真的。所以这并不总是正确的。

    如果您订阅了长寿命对象的事件(例如singleton对象或存储在中的application、session和cache中的对象),那么应该取消订阅事件是很重要的asp.net)使用短生命对象的方法(如页面、用户控件或web控件等)。

    例如

    UserControl uc = LoadControl("control.ascx") as UserControl;
    SomeObject so=Session["SomeObject"] as SomeObject;
    If(so!=null)
    {
        so.SomeEvent += new SomeEventHandler(uc.SomeMethod);
    }
    

    在这里,它应该从事件中取消订阅,以免导致内存泄漏。

        5
  •  0
  •   Jordão    14 年前

    你打电话给 controls.Clear 在小组中有足够的证据,你也应该注销事件。

    为此,您可以创建自己的控件集合,并重写 Clear 方法,然后创建使用新集合的自己的面板,该面板是从重写的 Controls 属性getter。