代码之家  ›  专栏  ›  技术社区  ›  sourcenouveau

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

  •  14
  • sourcenouveau  · 技术社区  · 14 年前

    当我在WPF中使用数据绑定时,我的目标控件正在侦听绑定源上的事件。例如,我可能有一个 ListView CollectionChanged 事件 ObservableCollection

    如果事件源的生存期预计将超过事件侦听器的生存期,则可能存在内存泄漏,并且 weak event pattern 应该使用。

    WPF数据绑定是否遵循弱事件模式?如果我的 可观测集合 列表视图 ,我的


    这就是为什么我怀疑WPF控件没有实现弱事件模式。如果他们这样做了,我希望两者都是 DerivedListView Collected! DerivedTextBlock Collected! 是。

    窗口1。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");
            }
        }
    }
    

    窗口1.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 回复  |  直到 14 年前
        1
  •  11
  •   ASanch    14 年前

    本质上,WPF控件本身与弱事件没有任何关系。相反,有些类与WPF的绑定引擎相关,它们实现弱事件模式。班级 PropertyChangedEventManager 实现VentManager。如果您使用Reflector,您将看到有几个类在MS.内部数据命名空间(特别是MS.内部数据.PropertyPathWorker类,它直接使用PropertyChangedEventManager)。WPF在内部使用这些对象来进行数据绑定。

    ItemsControls和CollectionChanged事件是另一回事,与绑定无关。看,你可以这样做listView.ItemsSource文件=myObservableCollection”,并且集合更改通知仍然有效。这里根本不涉及绑定对象。在这里,一组不同的“弱事件相关类”正在发挥作用。 ItemCollection ItemContainerGenerator 实现IWeakEventListener,它们与 CollectionChangedEventManager (实现VentManager)。

        2
  •  2
  •   Randolpho    14 年前

    您链接到的MSDN文章的第二句非常清楚地指出WPF确实使用弱事件模式。事实上,甚至可以说WPF 介绍

    我希望能找到一些明确说明“WPF控件实现弱事件模式”的文档

    在做了一些研究之后,我认为这个问题的答案是“不”,我认为 原因 答案是“不”,因为WPF并不期望UI控件是暂时的。当有一个 CollectionChangedEventManager 类专门为针对 CollectionChanged 事件时,支持数据绑定的控件似乎都没有实现 IWeakEventListener ,这是对集合使用弱事件所必需的。

    我认为模式和用法是为ViewModel而不是视图构建的,视图更可能是临时的而不是视图。

    编辑2:

    推荐文章