简体   繁体   English

ObservableCollection上的Observable.FromEventPattern

[英]Observable.FromEventPattern on ObservableCollection

I have a ClassWrapper class and a BaseClassWrapper class. 我有一个ClassWrapper类和一个BaseClassWrapper类。 The BaseClassWrapper has an object of type ClassDTO and inside it has an ObservableCollection that is what I want to "observe". BaseClassWrapper具有ClassDTO类型的对象,并且在其内部具有ObservableCollection,这就是我要“观察”的对象。 When I create an object of type "ClassWrapper" and add an item to the collection ClassWrapper.ClassDTO.MyCollection.Add(new OtherClass()) the observer does not work. 当我创建“ ClassWrapper”类型的对象并将一个项目添加到集合ClassWrapper.ClassDTO.MyCollection.Add(new OtherClass()) ,观察者将无法使用。

But if I create ClassDTO or an ObservableCollection inside ClassWrapper (not in BaseWrapper) it works perfectly. 但是,如果我在ClassWrapper(不是在BaseWrapper中)内创建ClassDTO或ObservableCollection,它会完美地工作。 Why does this happen? 为什么会这样?

public class ClassWrapper : BaseClassWrapper
{
    public ClassWrapper()
    {
        Observable.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>
                (x => ClassDTO.MyCollection.CollectionChanged += x, x => ClassDTO.MyCollection.CollectionChanged -= x)
            .Where(x => x.EventArgs.Action == NotifyCollectionChangedAction.Add ||
                        x.EventArgs.Action == NotifyCollectionChangedAction.Replace ||
                        x.EventArgs.Action == NotifyCollectionChangedAction.Remove)
            .Throttle(TimeSpan.FromMilliseconds(250))
            .Subscribe(x =>
            {
                RaisePropertyChanged(SomeProperty);
            });
    }
}

public abstract class BaseClassWrapper : ObservableObject // MVVM Light
{
    public ClassDTO ClassDTO { get; set; } = new ClassDTO();
}

public class ClassDTO
{
    public ObservableCollection<OtherClass> MyCollection { get; set; } = new ObservableCollection<OtherClass>();
}

I tried the code and added a new item every 100ms and was ... perplexed to say the least until I accidentally hovered over Throttle and saw : 我尝试了代码,每100毫秒添加了一个新项目,然后……至少我感到困惑,直到我不小心将鼠标悬停在Throttle并看到:

Ignores elements from an observable sequence which are followed by another element within a specified relative time duration. 忽略可观察序列中的元素,在指定的相对持续时间内,此元素之后是另一个元素。

I suspect, like me, you expected Throttle() to return the last item in a window. 我怀疑像我一样,您希望Throttle()返回窗口中的最后一项。 Even though its description in ReactiveX.io is 即使它在ReactiveX.io中的描述是

only emit an item from an Observable if a particular timespan has passed without it emitting another item 仅在经过特定时间跨度时才从Observable发出一项,而不发出另一项

And the documentation remarks say : 和文档备注说:

For streams that never have gaps larger than or equal to dueTime between elements, the resulting stream won't produce any elements. 对于元素之间的间隔永远不大于或等于DueTime的流,结果流将不产生任何元素。

In fact, I've used it this way in the past, but somehow I trip over the name each time until I remember that the actual operation is debouncing , not throttling. 实际上,我过去曾经使用过这种方式,但是每次我都以某种方式遍历该名称,直到我记得实际的操作是在反跳 ,而不是在节流。

When I slowed the timer to fire eg every 300 ms I started getting results. 当我放慢计时器触发时间(例如每300毫秒)时,我开始获得结果。

The operator that returns the last event in a window is Sample , not Throttle. 返回窗口中最后一个事件的运算符是Sample ,而不是Throttle。 If that's what you want, you should use 如果那是您想要的,则应使用

.Sample( TimeSpan.FromMilliseconds(300))

instead of Throttle . 而不是Throttle

Use Throttle if you want to update the UI only after notifications stop coming for 250 ms 如果仅通知停止发出250毫秒后才更新UI,请使用Throttle

Update 更新资料

To test this behaviour I created a console application. 为了测试此行为,我创建了一个控制台应用程序。 I added a couple of fixes to the question's code to allow it to compile : 我对问题的代码进行了一些修复,以使其得以编译:

public class ClassWrapper : BaseClassWrapper
{
    public string SomeProperty { get; set; }
    public ClassWrapper()
    {
        Observable.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>
                (x => ClassDTO.MyCollection.CollectionChanged += x, x => ClassDTO.MyCollection.CollectionChanged -= x)
            .Where(x => x.EventArgs.Action == NotifyCollectionChangedAction.Add ||
                        x.EventArgs.Action == NotifyCollectionChangedAction.Replace ||
                        x.EventArgs.Action == NotifyCollectionChangedAction.Remove)
            .Throttle( TimeSpan.FromMilliseconds(250))
            .Subscribe(x =>
            {
                RaisePropertyChanged( ()=> SomeProperty);
            });
    }
}

The application's Main method adds an item every 100ms. 应用程序的Main方法每100毫秒添加一个项目。 250ms after the last item is added, a single notification event is raised and a message gets printed: 添加最后一项后250毫秒,将引发单个通知事件并显示一条消息:

static async Task Main(string[] args)
{
    Console.WriteLine("Started");
    var c = new ClassWrapper();
    c.PropertyChanged += (sender, e) =>
    {
        Console.WriteLine($"Collection has {c.ClassDTO.MyCollection.Count} items");
    };

    for (int i = 0; i < 100; i++)
    {
        c.ClassDTO.MyCollection.Add(new OtherClass());
        await Task.Delay(100);

    }

    Console.ReadKey();
}    

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Observable.fromEventPattern TypedEventHandler - Observable.fromEventPattern TypedEventHandler 用 Observable.Create 包裹 Observable.FromEventPattern - Wrap Observable.FromEventPattern with Observable.Create 为什么Observable.FromEventPattern接受调度程序? - Why Observable.FromEventPattern take in a scheduler? Observable.FromEventPattern(addHandler,removeHandler)-简化吗? - Observable.FromEventPattern(addHandler, removeHandler ) - simplification? 何时使用Observable.FromEventPattern而不是Observable.FromEvent? - When to use Observable.FromEventPattern rather than Observable.FromEvent? 使用Observable.FromEventPattern在不活动或计数后执行操作 - Use Observable.FromEventPattern to perform action after inactivity or count 如何将SelectMany用于Observable.FromEventPattern序列上的异步逻辑? - How to use SelectMany for async logic on Observable.FromEventPattern sequence? 您如何向Observable.FromEventPattern中使用的事件注册/注销处理程序? - How do you register/unregister handlers to the event used in Observable.FromEventPattern? 在 Reactive Extensions for .NET 中使用 Observable.FromEventPattern 时如何避免任何阻塞? - How can I avoid any blocking when using Observable.FromEventPattern in Reactive Extensions for .NET? 当使用TestScheduler将事件触发到具有ObserveOn的Observable.FromEventPattern时,在下一个事件被触发之前不会观察到事件 - When using TestScheduler to fire events into Observable.FromEventPattern that has an ObserveOn, the events aren't observed until next event is fired
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM