从SortedList< MyClass>中的T.MyProperty上的所有属性更改事件获取IObservable. [英] Get IObservable from all Property Changed events on T.MyProperty in SortedList<MyClass>

查看:49
本文介绍了从SortedList< MyClass>中的T.MyProperty上的所有属性更改事件获取IObservable.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实现我 INotifyPropertyChanged 的类 MyClass ,并具有一些实现 PropertyChanged 的属性.当 MyClass.MyProperty 更改时, PropertyChanged 将按预期方式触发.另一个类包含 SortedList< MyClass> .我尝试将事件合并到包含 SortedSet< MyClass> 的类中的单个可观察对象中,并进行订阅,但是它似乎从来没有任何事件.这是我正在尝试的:

I have a Class, MyClass that implements INotifyPropertyChanged and has some properties that implement PropertyChanged. When MyClass.MyProperty changes, PropertyChanged fires as expected. Another class contains a SortedList<MyClass> .I've tried merging the events into a single observable in the class that contains the SortedSet<MyClass> and subscribing to it, but it doesn't seem to ever have any events. Here's what I'm trying:

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

我要获取的是一个单一的可观察对象,其中包含我的 SortedList< MyClass> 中每个项目的所有事件.我尝试使用ObservableCollection代替,但这不会改变任何东西,也不会期望如此,因为无论如何当包含的项目的属性发生改变时,它不会触发collectionchanged.我可以听 SortedList< MyClass> 中的各个元素,并看到PropertyChanged事件触发,但是我想要的是一个单个Observable,其中包含来自<中的所有元素的所有PropertyChanged事件流code> SortedList< MyClass> .

What I'm trying to get is a single observable that contains all of the events from every item in my SortedList<MyClass>. I've tried using ObservableCollection instead, but that doesn't change anything, nor would it be expected to, really, since it doesn't fire collectionchanged when a property of a contained item changes, anyway. I can listen to individual elements in SortedList<MyClass> and see the PropertyChanged event fire, but what I want is a single Observable that contains a stream of ALL of the PropertyChanged events from all of the elements in SortedList<MyClass>.

使用Rx似乎应该很容易做到这一点,但我似乎不知道该怎么做.

It seems like this should be something fairly easy to do using Rx, but I can't seem to figure out how.

推荐答案

我为RxCookBook撰写了有关该主题的文章,您可以在此处找到 https://github.com/LeeCampbell/RxCookbook/blob/master/Model/CollectionChange.md 有关PropertyChange通知的更多文章,请参见 https://github.com/LeeCampbell/RxCookbook/blob/master/Model/PropertyChange.md

I have produced an article for the RxCookBook on this subject that you can find here https://github.com/LeeCampbell/RxCookbook/blob/master/Model/CollectionChange.md Further article on PropertyChange notification is here https://github.com/LeeCampbell/RxCookbook/blob/master/Model/PropertyChange.md

它通过汇总 ObservableCollection< T> 中的更改来解决您的需求.通过使用 ObservableCollection< T> ,当从集合中添加或删除项目时,您还会收到通知.

It solves what you need by aggregating up the changes from an ObservableCollection<T>. By using the ObservableCollection<T> you also get notifications when items are added or removed from the collection.

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

If you dont want to use the ObservableCollection<T> (i.e. you only want to track properties at a given snapshot of the collection) then you will need to do something else. First I assume you have an INoftifyPropertyChanged to IObservable<T> extension method or you are just going to use the standard event to IObservable<T> methods.

接下来,您可以将值列表投影到更改序列列表中,即 IEnumerable< T> IEumerable< IObserable< T> .这使您可以使用 Observable.Merge 将更改列表展平到单个更改中.

Next you can project the List of values into a list of change sequences i.e. IEnumerable<T> to IEumerable<IObserable<T>>. This allows you to use Observable.Merge to flatten the list of changes in to a single stream of changes.

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

Here is a sample if you dont want to use the link above:

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

哪个会输出:

Lee is 33
Bob is 24

这篇关于从SortedList&lt; MyClass&gt;中的T.MyProperty上的所有属性更改事件获取IObservable.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆