Tôi đã xem xét sử dụng Rx trong một khung MVVM. Ý tưởng là sử dụng các truy vấn LINQ 'trực tiếp' trên bộ dữ liệu trong bộ nhớ để đưa dữ liệu vào Mô hình Xem để liên kết với.Sử dụng IObservable (Rx) làm thay thế INotifyCollectionChanged cho MVVM?
Trước đây, bạn có thể sử dụng INotifyPropertyChanged/INotifyCollectionChanged và thư viện nguồn mở được gọi là CLINQ. Tiềm năng với Rx và IObservable là di chuyển đến một ViewModel khai báo nhiều hơn bằng cách sử dụng các lớp Subject để truyền các sự kiện đã thay đổi từ mô hình nguồn thông qua View. Một chuyển đổi từ IObservable cho các giao diện databinding thường xuyên sẽ là cần thiết cho bước cuối cùng.
Vấn đề là Rx dường như không hỗ trợ thông báo rằng một thực thể đã bị xóa khỏi luồng. Ví dụ bên dưới.
Mã này hiển thị một POCO sử dụng lớp BehaviorSubject cho trạng thái trường. Mã đi vào để tạo ra một tập hợp các thực thể này và sử dụng Concat để hợp nhất các luồng bộ lọc với nhau. Điều này có nghĩa là bất kỳ thay đổi nào đối với POCO được báo cáo cho một luồng đơn lẻ.
Bộ lọc cho luồng này được thiết lập để lọc cho Xếp hạng == 0. Đăng ký chỉ đơn giản là kết quả đầu ra cho cửa sổ gỡ lỗi khi một thậm chí xảy ra.
Cài đặt Xếp hạng = 0 trên bất kỳ phần tử nào sẽ kích hoạt sự kiện. Nhưng thiết lập Xếp hạng trở lại 5 sẽ không thấy bất kỳ sự kiện nào.
Trong trường hợp CLINQ kết quả của truy vấn sẽ hỗ trợ INotifyCollectionChanged - để các mục được thêm và xóa khỏi kết quả truy vấn sẽ kích hoạt sự kiện chính xác để cho biết kết quả truy vấn đã thay đổi (mục được thêm hoặc xóa).
Cách duy nhất tôi có thể nghĩ đến địa chỉ này là thiết lập hai luồng với truy vấn ngược (kép). Một mục được thêm vào luồng ngược lại ngụ ý xóa khỏi resultset. Nếu không, tôi chỉ có thể sử dụng FromEvent và không làm cho bất kỳ mô hình thực thể nào quan sát được - điều này làm cho Rx chỉ là một Event Aggregator. Bất kỳ con trỏ?
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;
}
};
}
"Vấn đề là Rx dường như không hỗ trợ thông báo rằng một thực thể đã bị xóa khỏi luồng" - điều này là do IObservable không đại diện cho một bộ sưu tập liên tục, chỉ là một luồng không đồng bộ các giá trị. –