我在弄清楚如何做到这一点时遇到了问题。我有两个实施INotifyPropertyChanged
的实例(来源和目标),我正在跟踪PropertyChanged
事件。我想要做的是在source.PropertyChanged
被提出之前随时执行操作,直到target.PropertyChanged
被引发。我可以这样做:
INotifyPropertyChanged source;
INotifyPropertyChanged target;
var sourcePropertyChanged = Observable
.FromEvent<PropertyChangedEventArgs>(source, "PropertyChanged")
.Where(x => x.EventArgs.PropertyName == sourcePropertyName);
var targetPropertyChanged = Observable
.FromEvent<PropertyChangedEventArgs>(target, "PropertyChanged")
.Where(x => x.EventArgs.PropertyName == targetPropertyName);
sourcePropertyChanged
.TakeUntil(targetPropertyChanged)
.ObserveOnDispatcher()
.Subscribe(_ => /*Raises target.PropertyChanged for targetPropertyName*/);
我遇到的问题是我想忽略由操作引起的PropertyChanged
通知,并且只有在外部源引发PropertyChanged
事件时才停止获取值。是否有一种很好的方法可以实现这一目标?
答案 0 :(得分:4)
没有内置的方式来做你正在谈论的事情。这是一个简单的SkipWhen
实现,每次在“其他”序列上收到值时都会跳过下一个源值:
public static IObservable<TSource> SkipWhen(this IObservable<TSource> source,
IObservable<TOther> other)
{
return Observable.Defer<TSource>(() =>
{
object lockObject = new object();
Stack<TOther> skipStack = new Stack<TOther>();
other.Subscribe(x => { lock(lockObject) { skipStack.Push(x); });
return source.Where(_ =>
{
lock(lockObject);
{
if (skipStack.Count > 0)
{
skipStack.Pop();
return false;
}
else
{
return true;
}
}
});
});
}
您的代码会像这样更新(请参阅下面的注释):
INotifyPropertyChanged source;
INotifyPropertyChanged target;
// See the link at the bottom of my answer
var sourcePropertyChanged = source.GetPropertyChangeValues(x => x.SourceProperty);
// Unit is Rx's "void"
var targetChangedLocally = new Subject<Unit>();
var targetPropertyChanged = target.GetPropertyChangeValues(x => x.TargetProperty)
.SkipWhen(targetChangedLocally);
sourcePropertyChanged
.TakeUntil(targetPropertyChanged)
.ObserveOnDispatcher()
.Subscribe(_ =>
{
targetChangedLocally.OnNext();
/*Raises target.PropertyChanged for targetPropertyName*/
});
注意:我最近写了一篇关于a strongly typed IObservable wrapper around INotifyPropertyChanged events的博文;随意窃取该代码。
答案 1 :(得分:0)
没有内置方法,但您可以使用Where
扩展方法过滤掉事件,以便观察。过滤条件将是事件的发送者。我认为target.PropertyChanged
事件的发件人与其他来源引发的PropertyChanged
事件的发件人不同。
我不完全确定这是否是您可以使用的方法。
答案 2 :(得分:0)
在Rx中使用锁这种方式很好。锁是短暂的,不会调用用户代码。