我有一个ClassWrapper类和一个BaseClassWrapper类。 BaseClassWrapper具有ClassDTO类型的对象,并且在其内部具有ObservableCollection,这就是我要“观察”的对象。当我创建“ ClassWrapper”类型的对象并将一个项目添加到集合ClassWrapper.ClassDTO.MyCollection.Add(new OtherClass())
时,观察者将无法使用。
但是,如果我在ClassWrapper(不是在BaseWrapper中)内创建ClassDTO或ObservableCollection,它会完美地工作。为什么会这样?
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>();
}
答案 0 :(得分:2)
我尝试了代码,每100毫秒添加了一个新项目,然后……至少让我感到困惑,直到我不小心将鼠标悬停在Throttle
上并看到了:
忽略可观察序列中的元素,然后在指定的相对持续时间内跟随另一个元素。
我怀疑像我一样,您希望Throttle()
返回窗口中的最后一项。即使在ReactiveX.io中的描述是
仅在经过特定时间跨度时才从Observable中发射一项,而不发射另一项
文档说明说:
对于元素之间的间隙永远不大于或等于DueTime的流,结果流将不产生任何元素。
事实上,我过去曾经用过这种方式,但是每次我都会用这个名字来打翻,直到我记得实际的操作是反跳,而不是节制。
当我放慢计时器触发时间(例如每300毫秒)时,我就会开始获得结果。
返回窗口中最后一个事件的运算符是Sample,而不是Throttle。如果那是您想要的,则应使用
.Sample( TimeSpan.FromMilliseconds(300))
代替Throttle
。
如果您要仅在 通知停止发出250毫秒后更新用户界面,请使用Throttle
更新
为了测试此行为,我创建了一个控制台应用程序。我为问题的代码添加了一些修复程序,以使其可以编译:
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);
});
}
}
应用程序的Main
方法每100毫秒添加一个项目。添加最后一项后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();
}