[英]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.