J'ai quelque chose ici qui me prend vraiment au dépourvu.
J'ai une ObservableCollection de T qui est remplie d'éléments. J'ai également un gestionnaire d'événement attaché à l'événement CollectionChanged.
Quand vous Clair la collection, cela provoque un événement CollectionChanged avec e.Action défini sur NotifyCollectionChangedAction.Reset. C'est normal. Mais ce qui est bizarre, c'est que ni e.OldItems ni e.NewItems ne contiennent quoi que ce soit. Je m'attendrais à ce que e.OldItems soit rempli de tous les éléments qui ont été retirés de la collection.
Quelqu'un d'autre a vu ça ? Et si oui, comment l'ont-ils contourné ?
Un peu de contexte : J'utilise l'événement CollectionChanged pour attacher et détacher un autre événement et donc si je n'ai pas d'éléments dans e.OldItems ... je ne pourrai pas me détacher de cet événement.
CLARIFICATION : Je sais que la documentation n'a pas carrément qu'il doit se comporter de cette façon. Mais pour toute autre action, il m'informe de ce qu'il a fait. Donc, je suppose qu'il me le dirait ... dans le cas de Clear/Reset également.
Vous trouverez ci-dessous l'exemple de code si vous souhaitez le reproduire vous-même. Tout d'abord, le 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>
Ensuite, le code derrière :
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 };
}
}
0 votes
Pourquoi devez-vous désinscrire l'événement ? Dans quel sens vous abonnez-vous ? Les événements créent une référence à l'abonné détenu par le raisonneur, et non l'inverse. Si les raisonneurs sont des éléments d'une collection qui est vidée, ils seront vidés en toute sécurité et les références disparaîtront - pas de fuite. Si les éléments sont les abonnés et sont référencés par un éleveur, alors il suffit de mettre l'événement à null dans l'éleveur lorsque vous obtenez un Reset - pas besoin de désabonner individuellement les éléments.
0 votes
Croyez-moi, je sais comment ça marche. L'événement en question concernait un singleton qui est resté en place pendant un long moment... donc les éléments de la collection étaient les abonnés. Votre solution, qui consiste à attribuer la valeur null à l'événement, ne fonctionne pas... puisque l'événement doit quand même être déclenché... en notifiant éventuellement d'autres abonnés (pas nécessairement ceux de la collection).