1. ホーム
  2. wpf

[解決済み] ObservableCollectionのクリア時にe.OldItemsに項目がない場合

2023-01-30 22:26:29

質問

ちょっと気になることがあるのですが。

私はアイテムで満たされているTのObservableCollectionを持っています。また、CollectionChanged イベントに接続されたイベント ハンドラを持っています。

あなたが をクリアする をクリアすると、e.Action が NotifyCollectionChangedAction.Reset に設定された CollectionChanged イベントが発生します。OK、それは正常です。しかし、奇妙なのは、e.OldItemsもe.NewItemsも何も持っていないことです。 私はe.OldItemsがコレクションから削除されたすべての項目で満たされることを期待します。

他にこれを見た人はいますか?そして、もしそうなら、どのようにそれを回避したのでしょうか?

いくつかの背景。私は別のイベントをアタッチおよびデタッチするために CollectionChanged イベントを使用しており、したがって、私が e.OldItems ... に任意のアイテムを取得しない場合。そのため、e.OldItems にアイテムがない場合、そのイベントからデタッチすることができません。



CLARIFICATION。 私は、ドキュメントが 明白な は、このように動作しなければならないと明言していません。しかし、他のすべてのアクションでは、それが何をしたかを私に通知しています。ですから、私の仮定では、Clear/Reset の場合も同様に、私に通知してくれるはずです...。



以下は、自分で再現したい場合のサンプルコードです。まず、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 };
    }
}

どのように解決するのですか?

私はまだObservableCollectionが私が望んだように動作することを望むにもかかわらず、OK、以下のコードは私が最終的にやったことです。基本的には、TrulyObservableCollection という新しい T のコレクションを作成し、ClearItems メソッドをオーバーライドして、Clearing イベントを発生させるために使用しました。

この TrulyObservableCollection を使用するコードでは、この Clearing イベントを使用して、項目をループしています。 その時点でまだコレクション内にあるアイテム をループして、デタッチしたいイベント上でデタッチしています。

このアプローチが他の誰かの助けになることを願っています。

public class TrulyObservableCollection<T> : ObservableCollection<T>
{
    public event EventHandler<EventArgs> Clearing;
    protected virtual void OnClearing(EventArgs e)
    {
        if (Clearing != null)
            Clearing(this, e);
    }

    protected override void ClearItems()
    {
        OnClearing(EventArgs.Empty);
        base.ClearItems();
    }
}