WPF控件是否在绑定中使用弱事件?

M. *_*ley 14 data-binding wpf weak-events

当我在WPF中使用数据绑定时,我的目标控件正在侦听绑定源上的事件.例如,我可能正在ListView监听CollectionChangeda上的事件ObservableCollection.

如果事件源的生命周期预计超过事件侦听器的生命周期,则可能存在内存泄漏,应使用弱事件模式.

WPF数据绑定是否遵循弱事件模式?如果我的ObservableCollection生命比我的寿命长,我ListViewListView被垃圾收集吗?


这就是我怀疑WPF控件不实现弱事件模式的原因.如果他们这样做,我会期望两者DerivedListView Collected!DerivedTextBlock Collected!输出到控制台.相反,只有DerivedTextBlock Collected!.

修复代码中的错误后,将收集这两个对象.我不知道该怎么想.

Window1.xaml.cs

using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;

namespace LeakDetector
{
    public class DerivedListView : ListView
    {
        ~DerivedListView()
        {
            Console.WriteLine("DerivedListView Collected!");
        }
    }

    public class DerivedTextBlock : TextBlock
    {
        ~DerivedTextBlock()
        {
            Console.WriteLine("DerivedTextBlock Collected!");
        }
    }

    public partial class Window1 : Window
    {
        // The ListView will bind to this collection and listen for its
        // events. ObColl will hold a reference to the ListView.
        public ObservableCollection<int> ObColl { get; private set; }

        public Window1()
        {
            this.ObColl = new ObservableCollection<int>();
            InitializeComponent();

            // Trigger an event that DerivedListView should be listening for
            this.ObColl.Add(1);

            // Get rid of the DerivedListView
            this.ParentBorder.Child = new DerivedTextBlock();

            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            GC.WaitForPendingFinalizers();
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);

            this.ParentBorder.Child = null;

            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            GC.WaitForPendingFinalizers();
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);

            Console.WriteLine("Done");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Window1.xaml

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:LeakDetector"
    x:Class="LeakDetector.Window1"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    Height="300" Width="300"
    Title="Leak Detector">
    <Border x:Name="ParentBorder">
        <local:DerivedListView ItemsSource="{Binding Path=ObColl}" />
    </Border>
</Window>
Run Code Online (Sandbox Code Playgroud)

ASa*_*nch 10

实质上,WPF控件本身与弱事件无关.相反,有一些与WPF的绑定引擎相关的类实现了弱事件模式.PropertyChangedEventManager类实现了WeakEventManager.如果你使用Reflector,你会看到几个类在MS.Internal.Data命名空间中实现IWeakEventListener(特别是一个直接使用PropertyChangedEventManager的MS.Internal.Data.PropertyPathWorker类).WPF在内部使用这些对象来执行数据绑定.

ItemsControls和CollectionChanged事件是一个不同的故事,与Bindings无关.看,您可以在后面的代码中执行类似"listView.ItemsSource = myObservableCollection"的操作,并且收集更改的通知仍然有效.这里没有涉及绑定对象.在这里,一组不同的"弱事件相关类"正在发挥作用. ItemCollectionItemContainerGenerator实现了IWeakEventListener,它们与CollectionChangedEventManager(实现WeakEventManager)一起工作.