问题 不调用OnDetaching函数的行为


我有 WPF behavior 在具体控制上。当我关闭持有控件的窗口时 OnDetaching 函数未被调用。

行为继续存在(因为它注册的事件),尽管窗口不再存在(内存泄漏)。

为什么 OnDetaching 功能没有解雇****,我该如何解决?

protected override void OnAttached()
{
     base.OnAttached();

     this.AssociatedObject.MouseLeftButtonDown += AssociatedObject_PlotAreaMouseLeftButtonDown;
     this.AssociatedObject.MouseLeftButtonUp += AssociatedObject_PlotAreaMouseLeftButtonUp;
     this.AssociatedObject.MouseMove += AssociatedObject_PlotAreaMouseMove;
}

protected override void OnDetaching()
{
     base.OnDetaching();

     this.AssociatedObject.MouseLeftButtonDown -= AssociatedObject_PlotAreaMouseLeftButtonDown;
     this.AssociatedObject.MouseLeftButtonUp -= AssociatedObject_PlotAreaMouseLeftButtonUp;
     this.AssociatedObject.MouseMove -= AssociatedObject_PlotAreaMouseMove;
}

4149
2018-06-04 08:05


起源



答案:


OnAttached 当XAML解析器解析XAML并创建一个行为实例时,会调用该行为的实例,该行为将添加到作为DependencyAttached属性公开的目标控件的BehaviorCollection中。

但是,如果处理视图,则处理集合(行为集合), 它永远不会触发OnDetaching方法

如果行为未正确清理,则GC不会收集该行为,并且还会在该集合中保存BehaviorCollection和其他行为。这些行为旨在扩展AssociatedObject,只要您订阅AssociatedObject事件就好了,因为AssociatedObject(发布者)将会死亡,您的行为将由垃圾收集器收集。

一个很好的来源


另一种方法是处理窗口中的“关闭”事件(当用户点击右上方的“X”按钮时) OnDetaching  那里。

 <i:Interaction.Triggers>
        <i:EventTrigger EventName="Closing">
            <cmd:EventToCommand Command="{Binding CloseCommand}" />
        </i:EventTrigger>
 </i:Interaction.Triggers>

然后在View构造函数中关联处理程序:

MyWindow() 
{
    // Set up ViewModel, assign to DataContext etc.
    Closing += viewModel.OnWindowClosing;
}

并将处理程序添加到ViewModel:

public void OnWindowClosing(object sender, CancelEventArgs e) 
{
   // Cancel, OnDetaching, etc
}

10
2018-06-04 08:28





尝试订阅AssociatedObject.Unloaded事件,并在eventHander内部取消订阅所有鼠标事件。 行为OnDetaching()函数。并不总是在“时间”调用。


2
2018-02-28 13:35



请注意,如果将项目重新引入可视树,则您的行为将不再起作用; - Rune


答案:


OnAttached 当XAML解析器解析XAML并创建一个行为实例时,会调用该行为的实例,该行为将添加到作为DependencyAttached属性公开的目标控件的BehaviorCollection中。

但是,如果处理视图,则处理集合(行为集合), 它永远不会触发OnDetaching方法

如果行为未正确清理,则GC不会收集该行为,并且还会在该集合中保存BehaviorCollection和其他行为。这些行为旨在扩展AssociatedObject,只要您订阅AssociatedObject事件就好了,因为AssociatedObject(发布者)将会死亡,您的行为将由垃圾收集器收集。

一个很好的来源


另一种方法是处理窗口中的“关闭”事件(当用户点击右上方的“X”按钮时) OnDetaching  那里。

 <i:Interaction.Triggers>
        <i:EventTrigger EventName="Closing">
            <cmd:EventToCommand Command="{Binding CloseCommand}" />
        </i:EventTrigger>
 </i:Interaction.Triggers>

然后在View构造函数中关联处理程序:

MyWindow() 
{
    // Set up ViewModel, assign to DataContext etc.
    Closing += viewModel.OnWindowClosing;
}

并将处理程序添加到ViewModel:

public void OnWindowClosing(object sender, CancelEventArgs e) 
{
   // Cancel, OnDetaching, etc
}

10
2018-06-04 08:28





尝试订阅AssociatedObject.Unloaded事件,并在eventHander内部取消订阅所有鼠标事件。 行为OnDetaching()函数。并不总是在“时间”调用。


2
2018-02-28 13:35



请注意,如果将项目重新引入可视树,则您的行为将不再起作用; - Rune