Rx:忽略订阅者导致的更新

我在弄清楚如何做到这一点时遇到了问题。 我有两个实现INotifyPropertyChanged实例(源和目标),我正在跟踪两者的PropertyChanged事件。 我想要做的是在任何时候运行一个动作source.PropertyChanged ,直到target.PropertyChanged被引发。 我可以这样做,就像这样:

 INotifyPropertyChanged source; INotifyPropertyChanged target; var sourcePropertyChanged = Observable .FromEvent(source, "PropertyChanged") .Where(x => x.EventArgs.PropertyName == sourcePropertyName); var targetPropertyChanged = Observable .FromEvent(target, "PropertyChanged") .Where(x => x.EventArgs.PropertyName == targetPropertyName); sourcePropertyChanged .TakeUntil(targetPropertyChanged) .ObserveOnDispatcher() .Subscribe(_ => /*Raises target.PropertyChanged for targetPropertyName*/); 

我遇到的问题是我想忽略由操作引起的PropertyChanged通知,并且只有在外部源引发PropertyChanged事件时才停止获取值。 是否有一种很好的方法可以实现这一目标?

做你正在谈论的事情没有内置的方式。 这是一个简单的SkipWhen实现,每次在“其他”序列上接收到值时都会跳过下一个源值:

 public static IObservable SkipWhen(this IObservable source, IObservable other) { return Observable.Defer(() => { object lockObject = new object(); Stack skipStack = new Stack(); 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(); var targetPropertyChanged = target.GetPropertyChangeValues(x => x.TargetProperty) .SkipWhen(targetChangedLocally); sourcePropertyChanged .TakeUntil(targetPropertyChanged) .ObserveOnDispatcher() .Subscribe(_ => { targetChangedLocally.OnNext(); /*Raises target.PropertyChanged for targetPropertyName*/ }); 

注意:我最近写了一篇关于INotifyPropertyChanged事件的强类型IObservable包装器的博客; 随意窃取该代码。

没有内置方法,但您可以使用Where extension方法过滤掉事件,以便观察。 过滤条件将是事件的发送者。 我想target.PropertyChanged事件的发送者与另一个源引发的PropertyChanged事件的发送者不同。

我不完全确定这是否是您可以使用的方法。

在Rx中使用锁这种方式很好。 锁是短暂的,不会调用用户代码。