当我第一次开始写WPF的自定义控件,如果我想添加事件处理程序,我将在控件的OnApplyTemplate重写这样做,得到了模板部件后:删除事件处理程序
public void override OnApplyTemplate() {
if (addMenu != null) {
addMenu.Click -= addMenu_Click;
addMenu = null;
}
addMenu = (MenuItem)Template.FindName("PART_AddMenu", this);
addMenu.Click += addMenu_Click;
}
但是后来有一天我注意到OnApplyTemplate()并不总是在我期望的时候被调用,也就是说,当控件从视觉树中断开时。也就是说,使用上述技术,事件处理程序不会总是被删除。所以我想出了一个不同的方式:
public MyCustomControl()
{
Loaded += this_Loaded;
}
void this_Loaded(object sender, RoutedEventArgs e)
{
Unloaded += this_Unloaded;
addMenu = (MenuItem)Template.FindName("PART_AddMenu", this);
addMenu.Click += addMenu_Click;
}
void this_Unloaded(object sender, RoutedEventArgs e)
{
Unloaded -= this_Unloaded;
if (addMenu != null)
{
addMenu.Click -= addMenu_Click;
addMenu = null;
}
}
这种方式似乎有伎俩。是否每个人都认为这是在自定义控件中连接和删除事件处理程序的更好方法?如果不是,那为什么?
你是对的,我想防止挂在引用,因为我已经注意到它发生在性能调整过程中。我不确定具体的原因,所以我宁愿使用新技术来安全地玩。关于你的TabItem例子,我知道发生了什么,但我想不出一个问题。 – HappyNomad 2011-06-15 13:18:54
只有父对象将其事件解析为子对象时才会发生泄漏(从而保留对子对象的第二次引用)。 – 2011-06-15 14:40:54
如果我正确地关注你,那么在上面的例子中,“父对象”是自定义控件,“子对象”是addMenu(模板部分)。由于自定义控件将addMenu存储在专用字段中,因此旧技术(使用OnApplyTemplate)会发生泄漏。 – HappyNomad 2011-06-15 20:32:33