wpf - 清除 ObservableCollection 时,e.OldItems 中没有项目

标签 wpf observablecollection

这里有一些东西确实让我措手不及。

我有一个 T 的 ObservableCollection,其中充满了项目。我还有一个附加到 CollectionChanged 事件的事件处理程序。

当您清除集合时,它会引发 CollectionChanged 事件,并将 e.Action 设置为 NotifyCollectionChangedAction.Reset。好吧,这很正常。但奇怪的是,e.OldItems 和 e.NewItems 中都没有任何内容。 我希望 e.OldItems 填充从集合中删除的所有项目。

还有人看过这个吗?如果是这样,他们是如何解决这个问题的?

一些背景:我正在使用 CollectionChanged 事件来附加和分离另一个事件,因此如果我没有在 e.OldItems 中获得任何项目...我将无法从该事件分离。


澄清: 我确实知道文档并没有完全声明它必须以这种方式运行。但对于其他所有操作,它都会通知我它做了什么。所以,我的假设是它会告诉我......在清除/重置的情况下也是如此。


如果您想自己重现,下面是示例代码。首先关闭 xaml:

<Window
    x:Class="ObservableCollection.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1"
    Height="300"
    Width="300"
>
    <StackPanel>
        <Button x:Name="addButton" Content="Add" Width="100" Height="25" Margin="10" Click="addButton_Click"/>
        <Button x:Name="moveButton" Content="Move" Width="100" Height="25" Margin="10" Click="moveButton_Click"/>
        <Button x:Name="removeButton" Content="Remove" Width="100" Height="25" Margin="10" Click="removeButton_Click"/>
        <Button x:Name="replaceButton" Content="Replace" Width="100" Height="25" Margin="10" Click="replaceButton_Click"/>
        <Button x:Name="resetButton" Content="Reset" Width="100" Height="25" Margin="10" Click="resetButton_Click"/>
    </StackPanel>
</Window>

接下来是后面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;

namespace ObservableCollection
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            _integerObservableCollection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_integerObservableCollection_CollectionChanged);
        }

        private void _integerObservableCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Move:
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                    break;
                default:
                    break;
            }
        }

        private void addButton_Click(object sender, RoutedEventArgs e)
        {
            _integerObservableCollection.Add(25);
        }

        private void moveButton_Click(object sender, RoutedEventArgs e)
        {
            _integerObservableCollection.Move(0, 19);
        }

        private void removeButton_Click(object sender, RoutedEventArgs e)
        {
            _integerObservableCollection.RemoveAt(0);
        }

        private void replaceButton_Click(object sender, RoutedEventArgs e)
        {
            _integerObservableCollection[0] = 50;
        }

        private void resetButton_Click(object sender, RoutedEventArgs e)
        {
            _integerObservableCollection.Clear();
        }

        private ObservableCollection<int> _integerObservableCollection = new ObservableCollection<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
    }
}

最佳答案

它并不声称包含旧项目,因为重置并不意味着列表已被清除

这意味着发生了一些戏剧性的事情,并且计算添加/删除的成本很可能超过从头开始重新扫描列表的成本......所以这就是你应该做的。

MSDN 建议将整个集合重新排序为重置候选者的示例。

重申一下。 重置并不意味着清楚,它意味着您对列表的假设现在无效。将其视为一个全新的列表。 Clear 恰好是这种情况的一个例子,但很可能还有其他例子。

一些例子:
我有一个像这样的列表,其中包含很多项目,并且它已被数据绑定(bind)到 WPF ListView 以在屏幕上显示。
如果您清除列表并引发 .Reset 事件,性能几乎是即时的,但如果您引发许多单独的 .Remove 事件,则性能非常糟糕,因为WPF 将一项一项地删除。 我还在自己的代码中使用了 .Reset 来指示列表已重新排序,而不是发出数千个单独的 Move 操作。与 Clear 一样,当引发许多单独的事件时,性能会受到很大影响。

关于wpf - 清除 ObservableCollection 时,e.OldItems 中没有项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/224155/

相关文章:

wpf - 半透明背景的文本框

c# - 如何将 'hermite' 曲线转换为贝塞尔曲线?

c# - 将 IList<T> 附加到 ObservableCollection<T>

c# - 使用数据绑定(bind)获取 WPF Listview 以显示 ObservableCollection<T>

时间:2019-03-17 标签:c#ObservableCollection: How to implement CollectionChanged event

c# - 当项目直接添加到数据库时,ObservableCollection 不会更新

wpf - 在WPF中使用MS ReportViewer

wpf - 从代码隐藏设置 ContentControls 内容属性会引发异常 'value does not fall in range'

c# - 将 SolidColorBrush 绑定(bind)到背景,绑定(bind)错误

c# - 在 ObservableCollection.CollectionChanged 上运行昂贵的操作