从SortedList <MyClass>中的T.MyProperty上的所有Property Changed事件中获取IObservable

Dan*_*nks 7 .net c# system.reactive

我有一个Class,MyClass它实现INotifyPropertyChanged并具有一些实现的属性PropertyChanged.当MyClass.MyProperty变化,PropertyChanged如预期火灾.另一个类包含一个.SortedList<MyClass>我已经尝试将事件合并到包含该类的类中的单个observable中SortedSet<MyClass>和订阅它,但它似乎没有任何事件.这是我正在尝试的:

Observable.Merge(MySortedList.ToObservable())
   .Subscribe(evt => Console.WriteLine("{0} changed", evt.MyProperty));
Run Code Online (Sandbox Code Playgroud)

我想要得到的是一个单一的observable,它包含了我所有项目中的所有事件SortedList<MyClass>.我已经尝试过使用ObservableCollection,但是这并没有改变任何东西,也没有预料到真的,因为当包含项的属性发生变化时,它不会触发collectionchanged.我可以听取单个元素SortedList<MyClass>并查看PropertyChanged事件触发器,但我想要的是一个包含来自所有元素的所有PropertyChanged事件的流的单个Observable SortedList<MyClass>.

看起来这应该是使用Rx相当容易的事情,但我似乎无法弄清楚如何.

Lee*_*ell 9

我在这个主题上为RxCookBook制作了一篇文章,你可以在这里找到 https://github.com/LeeCampbell/RxCookbook/blob/master/Model/CollectionChange.md 关于PropertyChange通知的更多文章在这里https:// github. COM/LeeCampbell/RxCookbook /斑点/主/型号/ PropertyChange.md

它通过聚合来自的变化来解决您的需求ObservableCollection<T>.通过使用,ObservableCollection<T>您还可以在从集合中添加或删除项目时收到通知.

如果您不想使用ObservableCollection<T>(即您只想跟踪集合的给定快照的属性),那么您将需要执行其他操作.首先,我假设你有一个INoftifyPropertyChangedIObservable<T>扩展方法,或者你只是要使用标准的事件IObservable<T>的方法.

接下来,您可以投射的值列表为变化序列的列表即IEnumerable<T>IEumerable<IObserable<T>>.这允许您使用Observable.Merge以将更改列表展平为单个更改.

如果您不想使用上面的链接,请参阅以下示例:

void Main()
{
    var myList = new List<MyThing>{
        new MyThing{Name="Lee", Age=31},
        new MyThing{Name="Dave", Age=37},
        new MyThing{Name="Erik", Age=44},
        new MyThing{Name="Bart", Age=24},
        new MyThing{Name="James", Age=32},
    };

    var subscription = Observable.Merge(myList.Select(t=>t.OnAnyPropertyChanges()))
                .Subscribe(x=>Console.WriteLine("{0} is {1}", x.Name, x.Age));

    myList[0].Age = 33;
    myList[3].Name = "Bob";

    subscription.Dispose();
}

// Define other methods and classes here
public class MyThing : INotifyPropertyChanged
{
private string _name;
private int _age;

public string Name
{
    get { return _name; }
    set
    {
        _name = value;
        OnPropertyChanged("Name");
    }
}

public int Age
{
    get { return _age; }
    set
    {
        _age = value;
        OnPropertyChanged("Age");
    }
}

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
    var handler = PropertyChanged;
    if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}

public static class NotificationExtensions
{
    /// <summary>
    /// Returns an observable sequence of the source any time the <c>PropertyChanged</c> event is raised.
    /// </summary>
    /// <typeparam name="T">The type of the source object. Type must implement <seealso cref="INotifyPropertyChanged"/>.</typeparam>
    /// <param name="source">The object to observe property changes on.</param>
    /// <returns>Returns an observable sequence of the value of the source when ever the <c>PropertyChanged</c> event is raised.</returns>
    public static IObservable<T> OnAnyPropertyChanges<T>(this T source)
        where T : INotifyPropertyChanged
    {
            return Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
                                handler => handler.Invoke,
                                h => source.PropertyChanged += h,
                                h => source.PropertyChanged -= h)
                            .Select(_=>source);
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个会输出:

Lee is 33
Bob is 24
Run Code Online (Sandbox Code Playgroud)