WPF でデータ バインディングを使用すると、ターゲット コントロールがバインディング ソースのイベントをリッスンします。たとえば、でイベントをListView
リッスンしている場合があります。CollectionChanged
ObservableCollection
イベント ソースの有効期間がイベント リスナーの有効期間を超えることが予想される場合は、メモリ リークが発生する可能性があるため、弱いイベント パターンを使用する必要があります。
WPF データバインディングは弱いイベントパターンに従いますか? 私の寿命が私のObservableCollection
寿命よりも長い場合、ガベージコレクションの対象になりますか?ListView
ListView
これが、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");
}
}
}
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>