He estado buscando el uso de Rx en un marco MVVM. La idea es usar consultas LINQ "en vivo" sobre conjuntos de datos en memoria para proyectar datos en Modelos de visualización para vincular.¿Cómo utilizar IObservable (Rx) como reemplazo de INotifyCollectionChanged para MVVM?
Anteriormente esto ha sido posible con el uso de INotifyPropertyChanged/INotifyCollectionChanged y una biblioteca de código abierto llamada CLINQ. El potencial con Rx e IObservable es pasar a un modelo de vista mucho más declarativo utilizando clases de materias para propagar eventos modificados desde el modelo de origen hasta la vista. Para el último paso, se necesitaría una conversión de IObservable a las interfaces de enlace de datos normales.
El problema es que Rx no parece ser compatible con la notificación de que una entidad se ha eliminado de la transmisión. Ejemplo a continuación.
El código muestra un POCO que utiliza la clase BehaviorSubject para el estado del campo. El código continúa para crear una colección de estas entidades y utiliza Concat para combinar las secuencias de filtro. Esto significa que cualquier cambio en las POCO se informa a una sola transmisión.
Un filtro para esta secuencia está configurado para filtrar para Rating == 0. La suscripción simplemente envía el resultado a la ventana de depuración cuando se produce una actualización.
La configuración Rating = 0 en cualquier elemento activará el evento. Pero al volver a establecer la clasificación en 5, no se verán eventos.
En el caso de CLINQ, la salida de la consulta admitirá INotifyCollectionChanged, de modo que los elementos agregados y eliminados del resultado de la consulta activarán el evento correcto para indicar que el resultado de la consulta ha cambiado (un elemento agregado o eliminado).
La única forma en que se me ocurre abordar esto es configurar dos flujos con consultas de oposición (doble). Un elemento agregado a la secuencia opuesta implica la eliminación del conjunto de resultados. De lo contrario, podría usar FromEvent y no hacer que ninguno de los modelos de entidades sean observables, lo que hace que Rx sea más un simple agregador de eventos. ¿Alguna sugerencia?
using System;
using System.ComponentModel;
using System.Linq;
using System.Collections.Generic;
namespace RxTest
{
public class TestEntity : Subject<TestEntity>, INotifyPropertyChanged
{
public IObservable<string> FileObservable { get; set; }
public IObservable<int> RatingObservable { get; set; }
public string File
{
get { return FileObservable.First(); }
set { (FileObservable as IObserver<string>).OnNext(value); }
}
public int Rating
{
get { return RatingObservable.First(); }
set { (RatingObservable as IObserver<int>).OnNext(value); }
}
public event PropertyChangedEventHandler PropertyChanged;
public TestEntity()
{
this.FileObservable = new BehaviorSubject<string>(string.Empty);
this.RatingObservable = new BehaviorSubject<int>(0);
this.FileObservable.Subscribe(f => { OnNotifyPropertyChanged("File"); });
this.RatingObservable.Subscribe(f => { OnNotifyPropertyChanged("Rating"); });
}
private void OnNotifyPropertyChanged(string property)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(property));
// update the class Observable
OnNext(this);
}
}
public class TestModel
{
private List<TestEntity> collection { get; set; }
private IDisposable sub;
public TestModel()
{
this.collection = new List<TestEntity>() {
new TestEntity() { File = "MySong.mp3", Rating = 5 },
new TestEntity() { File = "Heart.mp3", Rating = 5 },
new TestEntity() { File = "KarmaPolice.mp3", Rating = 5 }};
var observableCollection = Observable.Concat<TestEntity>(this.collection.Cast<IObservable<TestEntity>>());
var filteredCollection = from entity in observableCollection
where entity.Rating==0
select entity;
this.sub = filteredCollection.Subscribe(entity =>
{
System.Diagnostics.Debug.WriteLine("Added :" + entity.File);
}
);
this.collection[0].Rating = 0;
this.collection[0].Rating = 5;
}
};
}
"El problema es que Rx no parece ser compatible con la notificación de que una entidad se ha eliminado de la secuencia", esto se debe a que IObservable no representa una colección persistente, solo una secuencia de valores asincrónica. –