6

ListBox の ItemsSource を List にバインドすると、バインディング エンジンは、コントロールがなくなった後もリスト要素を保持します。これにより、すべてのリスト要素がメモリに残ります。ObservalbleCollection を使用すると、この問題はなくなります。なぜこれが起こるのですか?

window タグ内の xaml

<Grid>
    <StackPanel>
        <ContentControl Name="ContentControl">
            <ListBox ItemsSource="{Binding List, Mode=TwoWay}" DisplayMemberPath="Name"/>
        </ContentControl>
        <Button Click="Button_Click">GC</Button>
    </StackPanel>
</Grid>

コードビハインド:

public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel();
    }

private void Button_Click(object sender, RoutedEventArgs e)
    {
        this.DataContext = null;
        ContentControl.Content = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }

ビューモデル

class ViewModel : INotifyPropertyChanged
{
    //Implementation of INotifyPropertyChanged ...

    //Introducing ObservableCollection as type resolves the problem
    private IEnumerable<Person> _list = 
            new List<Person> { new Person { Name = "one" }, new Person { Name = "two" } };

    public IEnumerable<Person> List
    {
        get { return _list; }
        set
        {
            _list = value;
            RaisePropertyChanged("List");
        }
    }

class Person
{
    public string Name { get; set; }
}

編集: 個人インスタンスのリークを確認するために、ANTS と .Net メモリ プロファイラーを使用しました。どちらも、GC ボタンを押した後、バインディング エンジンだけが人物オブジェクトへの参照を保持していることを示しています。

4

3 に答える 3