wpf mvvm inotifycollectionchanged

wpf - ¿Puedo revertir los cambios de colección en el evento cambiado de colección?



mvvm inotifycollectionchanged (3)

Teniendo en cuenta que obtiene el remitente del evento como un objeto (es decir, el primer parámetro del evento) y la lista de objetos que se modificaron, sí puede hacerlo. Sin embargo, no lo aconsejaría. Si se encuentra con tal condición, proporcione un método en ViewModel que se proporciona con EventArgs y deje que haga el trabajo. La vista no es el lugar para hacer lógica.

Mejor aún: compruebe la condición en el ViewModel mismo (es decir, en los comandos que se pueden responder para agregar / eliminar). El modelo de vista es respondible por el estado de la información, así que mantén tu lógica allí. La vista está allí para mostrar los datos.

Tengo 2 vistas de lista ... y agrego / elimino botones entre ellas.

En el evento change collection de una lista-vista-colección en viewmodel, ¿puedo deshacer los cambios para una condición en particular?


Puede manejar el evento CollectionChanged de ObservableCollection para hacer una copia de seguridad (a través de la máquina virtual o lo que sea) de los valores anteriores (vea la propiedad NotifyCollectionChangedEventArgs.OldItems ) y recuperarlos cuando sea necesario, es decir, cuando el usuario haga clic en ''Deshacer'', etc.

Actualización En referencia a los comentarios a continuación:

Si desea retrotraer la colección desde el manejador de eventos CollectionChanged , cree un indicador donde escapa del manejador de una llamada recursiva (no probada con la aplicación de subprocesos múltiples), aquí hay un ejemplo simple, puede ajustarlo fácilmente a calce en su 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; } } }


La respuesta de Shimmy no funcionó para mí en una aplicación de la Tienda Windows, aún se encontrará con problemas de reentrada y obtendrá una InvalidOperationException dice "No se puede cambiar ObservableCollection durante un evento CollectionChanged".

Tuve que usar el despachador de la interfaz de usuario y deshabilitar / habilitar el controlador de eventos para evitar estos problemas.

Tenga cuidado: este es un truco, y los diseñadores del framework hicieron todo lo posible para evitar que lo haga. Entonces, si quiere ignorar su advertencia, tenga cuidado de no dispararse en el pie.

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(); } }

Esto evitará la excepción, evite llamar al manejador recursivamente y actualice la IU correctamente.