Puis-je rollback collection change sur l'événement changé de collection?
-
13-10-2019 - |
Question
J'ai 2 vues liste ... et ajouter / supprimer des boutons entre eux.
Lors de la collecte événement changé d'une liste-view-collection viewmodel, puis-je rollback les changements pour une condition particulière?
La solution
Vous pourriez gérer l'événement CollectionChanged
du ObservableCollection
sauvegarder ( via la machine virtuelle ou autre) les anciennes valeurs (voir la propriété de NotifyCollectionChangedEventArgs.OldItems
) et les récupérer en cas de besoin dire lorsque l'utilisateur clique sur Annuler de 'etc.
Mise à jour En ce qui concerne les commentaires ci-dessous:
Si vous ne voulez rollback la collection de withing l'événement gestionnaire de CollectionChanged
, créez un drapeau où vous échapper le gestionnaire d'un appel récursif (non testé avec application multi-thread), voici un exemple simple, vous pouvez facilement ruser pour tenir dans votre V / VM.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var x = new ObservableCollection<string>();
x.CollectionChanged +=
new NotifyCollectionChangedEventHandler(x_CollectionChanged);
x.Add("asdf");
x.Remove("asdf");
}
bool rollingBack = false;
void x_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (rollingBack) return;
if (e.Action == NotifyCollectionChangedAction.Remove)
{
if (e.OldItems.Contains("asdf"))
{
var oc = (ObservableCollection<string>)sender;
rollingBack = true;
oc.Add("asdf");
rollingBack = false;
}
}
}
Autres conseils
Étant donné que vous obtenez l'expéditeur de l'événement comme un objet (ie. Le premier paramètre de l'événement) et la liste des objets qui ont été modifiés, oui vous pouvez le faire. Je ne conseillerais pas que si. Si vous rencontrez une telle condition, fournir une méthode sur le ViewModel qui est fourni avec le EventArgs
, et laissez-le faire le travail. La vue est pas le lieu de faire la logique.
Mieux encore: pour vérifier l'état dans le ViewModel lui-même (par exemple dans les commandes qui sont responseable pour l'ajout / suppression)! Le viewmodel est responseable pour l'état des informations, donc gardez votre logique là-bas. La vue est juste là pour afficher les données.
La réponse de Shimmy n'a pas fonctionné pour moi sur une application Windows Store, vous aurez toujours rencontrez des problèmes réentrance et obtenir une InvalidOperationException
disant « ne peut pas changer ObservableCollection lors d'un événement CollectionChanged. »
Je devais utiliser le répartiteur de l'interface utilisateur et désactiver / activer le gestionnaire d'événements pour éviter ces problèmes.
Soyez prévenu: c'est un hack, et les concepteurs de cadres est allé très loin pour vous empêcher de faits et gestes ce. Donc, si vous voulez ignorer leur avertissement, attention à ne pas vous tirer dans le pied.
Items.CollectionChanged += ItemsChanged;
private async void ItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if(condition)
{
//rollback
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal, () => {
//disable/enable event handler
Items.CollectionChanged -= ItemsChanged;
Items.Remove(e.NewItems[0]);
Items.CollectionChanged += ItemsChanged;
})).AsTask();
}
}
Cela évitera l'exception, évitez d'appeler le gestionnaire récursive, et mettre à jour l'interface utilisateur correctement.