在XAML用户控件中删除DataContextChanged/Loaded事件处理程序

5
为了减少内存泄漏,我试图找出在将事件处理程序添加到 XAML 用户控件上的“DataContextChanged”事件或“Loaded”事件之后(即,UserControl.xaml.cs)是否可以解决问题。
    public MyUserControl()
    {
        InitializeComponent();
        DataContextChanged += new DependencyPropertyChangedEventHandler(MyUserControl_DataContextChanged);
        Loaded += new RoutedEventHandler(MyUserControl_Loaded);
    }

如果我需要移除它,WPF会处理这个问题吗?还是我需要手动移除它们?
1个回答

6
短而直接的回答是——不需要。
只有当处理程序会保持对象根源,即防止其垃圾收集时,才需要删除它们。如果您创建了一个子对象,并将其事件处理程序之一指向父对象,则不会发生这种情况,因为没有对子对象的悬空引用。
如果您创建了一个子对象,并且父对象将其事件处理程序之一指向该子对象,那么现在父对象具有对子对象的引用,它将使其保持活动状态(根源)。
在你提到的情况下,这是完全内部的——你在类内部添加一个对自己类的引用。当用户控件被销毁时,就不会在另一个类的事件处理程序中留下引用,因此不需要删除事件处理程序。

新的RoutedEventHandler()部分创建了一个外部于用户控件的对象实例。RoutedEventHandler持有对用户控件的引用(因为这就是事件处理程序的作用),而用户控件则持有对RoutedEventHandler的引用(因为它保留了已注册对象的集合)。因此,它们相互引用,意味着两个对象都被保持活动状态。因此,我不同意您的说法。 - Nick
@Nick,你的断言是不正确的。+= RoutedEventHandler 不会创建一个持有对该类的引用的新的外部对象。如果你不相信,请使用 CLR 分析器。你会发现上述模式不会导致根对象。 - Ed Bayiates
@Nick,请查看这里的答案,以获得更详细的解释:https://dev59.com/bEbRa4cB1Zd3GeqP03-R - Ed Bayiates

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接