【问题标题】:How to deinitialize a FrameworkElement?如何取消初始化 FrameworkElement?
【发布时间】:2015-02-17 05:00:02
【问题描述】:

我们有一个派生自 FrameworkElement 的类,它不受我们控制。 此类在OnInitialize 方法中注册事件处理程序。

由于 FrameworkElement 不提供 OnInitialize 的对应项,正确清理此类的模式是什么?

它仍然是根目录,因为它的任何部分都不会删除导致泄漏的 EventHandler。

【问题讨论】:

    标签: c# wpf frameworkelement


    【解决方案1】:

    没有“取消初始化”之类的东西。当无法在其构造函数中完全初始化对象时使用初始化方法,因为它依赖于在构造期间不可用的数据。在这些情况下,构造分为两个阶段:第一步在无参数构造函数中执行,第二步在初始化方法中执行,如OnInitialize,在外部数据可用后

    你描述的是对象处理,通过调用对象的Dispose方法来执行。一个编写良好的类应该清理其数据,释放所有外部资源释放所有事件处理程序。

    视觉元素通常在其生命周期中有另一个步骤,由 OnLoad/OnUnload 方法处理。当元素实际放置在 XAML 视图中并连接到其他 UI 元素时,会发生加载步骤。事件处理程序应在 OnLoad 方法中注册并在 OnUnload 方法中删除。

    如果元素没有 Dispose 方法,您可以引发 Unload 事件来强制清理,尽管这有点小技巧:

    control.RaiseEvent(new RoutedEventArgs(FrameworkElement.UloadedEvent))
    

    【讨论】:

    • 有问题的类在 AvalonDock 库中。没有可用的概念文件证明未清理事件的原因。
    • 每个表单只能创建一个停靠窗口。考虑到对接用于应用程序的主要形式,这应该在应用程序的生命周期中只发生一次。您是否在运行时创建了很多表单?您是处理表单、重复使用它们还是将它们留作垃圾收集?
    • 我们正在按需创建 ViewModel(及其作为 Anchorable 的 View)。就像 Visual Studio 不会在启动时创建所有可能的窗口一样。 LayoutContent 有一个 Closing 事件和一个受保护的 OnClosing 来支持这一点。 Profilling 向我们展示了关闭窗口正确地处理了我们的 ViewModel,但以下隐式“释放” LayoutDocumentPaneGroupControl 失败,因为它仍然具有活动的事件处理程序。没有不支持关闭的痕迹。
    【解决方案2】:

    使用弱事件模式。特别是,使用WeakEventManager 实现订阅事件(或者,如果.NET 4.5 是一个选项,更好的是它的通用版本WeakEventManager<TEventSource, TEventArgs>)。

    【讨论】:

      【解决方案3】:

      使用Dispatcher.ShutdownStarted 事件。

      将此添加到构造函数中:

      Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
      

      并将您的清理代码添加到此方法中:

      private void Dispatcher_ShutdownStarted(object sender, EventArgs e)
      {
          Stop();
      }
      

      【讨论】:

        猜你喜欢
        • 2020-09-15
        • 1970-01-01
        • 2019-09-18
        • 1970-01-01
        • 1970-01-01
        • 2016-12-17
        • 1970-01-01
        • 2021-10-03
        • 1970-01-01
        相关资源
        最近更新 更多