Используют ли элементы управления WPF слабые события в своих привязках? - PullRequest
14 голосов
/ 14 сентября 2010

Когда я использую привязку данных в 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>

Ответы [ 2 ]

10 голосов
/ 15 сентября 2010

По сути, сами элементы управления WPF не имеют ничего общего со слабыми событиями. Вместо этого существуют определенные классы, связанные с механизмом связывания WPF, которые реализуют шаблон слабых событий. Класс PropertyChangedEventManager реализует WeakEventManager. И если вы используете Reflector, вы увидите, что несколько классов реализуют IWeakEventListener в пространстве имен MS.Internal.Data (одним из них, в частности, является класс MS.Internal.Data.PropertyPathWorker, который напрямую использует PropertyChangedEventManager). Эти объекты используются WPF для привязки данных.

События ItemsControls и CollectionChanged - это отдельная история, которая не имеет ничего общего с привязками. Видите, вы могли бы сделать что-то вроде «listView.ItemsSource = myObservableCollection» в коде позади, и уведомление об изменении коллекции все равно будет работать. Никакие Связывающие объекты здесь не задействованы вообще. Здесь другой набор "классов, связанных со слабыми событиями", находится в игре. ItemCollection и ItemContainerGenerator реализуют IWeakEventListener, и они работают совместно с CollectionChangedEventManager (который реализует WeakEventManager).

2 голосов
/ 14 сентября 2010

Во втором предложении статьи MSDN, на которую вы ссылаетесь, довольно четко говорится, что WPF действительно использует шаблон слабых событий.Фактически, речь идет о том, что WPF представил шаблон.

Редактировать:

Я надеялся найтинекоторая документация, в которой прямо указано «элементы управления WPF реализуют шаблон слабых событий».- emddudley

После некоторого исследования я думаю, что ответ на этот вопрос - "нет", и я думаю, что причина ответ - "нет", что WPFНе ожидайте, что элементы управления пользовательского интерфейса будут временными.Хотя существует класс CollectionChangedEventManager, созданный специально для слабых событий против события CollectionChanged, ни один из элементов управления, поддерживающих привязку данных, не реализует IWeakEventListener, что было бы необходимоиспользовать слабые события против коллекции.

Я думаю, что шаблон и использование построены для ViewModel, а не для View, который, скорее всего, будет временным, чем View.

Edit2:

После исправления ошибки в коде оба объекта собираются.Поэтому я считаю, что элементы управления WPF используют шаблон слабых событий.

Интересный результат.Если они реализуют Слабые События, они должны сделать это внутренне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...