C# Rx:忽略由订阅者引起的更新
我不知道怎么做。我有两个实例(源和目标)实现了C# Rx:忽略由订阅者引起的更新,c#,silverlight,silverlight-4.0,system.reactive,C#,Silverlight,Silverlight 4.0,System.reactive,我不知道怎么做。我有两个实例(源和目标)实现了INotifyPropertyChanged,我正在跟踪这两个实例的PropertyChanged事件。我想做的是在任何时候运行一个操作,直到source.PropertyChanged被提升,直到target.PropertyChanged被提升。我可以这样做: INotifyPropertyChanged source; INotifyPropertyChanged target; var sourcePropertyChanged = Obs
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*/);
INotifyPropertyChanged源;
INotifyPropertyChanged目标;
var sourcePropertyChanged=可观测
.FromEvent(来源,“PropertyChanged”)
。其中(x=>x.EventArgs.PropertyName==sourcePropertyName);
var targetPropertyChanged=可观测
.FromEvent(目标,“财产变更”)
。其中(x=>x.EventArgs.PropertyName==targetPropertyName);
sourcePropertyChanged
.TakeUntil(targetPropertyChanged)
.ObserveOnDispatcher()
.Subscribe(=>/*为targetPropertyName*/)引发target.PropertyChanged;
我遇到的问题是,我想忽略由操作引起的
PropertyChanged
通知,仅当外部源引发PropertyChanged
事件时才停止获取值。有没有一个好的方法来实现这一点?没有内在的方法来完成你所说的。下面是一个简单的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;
}
}
});
});
}
public static IObservable SkipWhen(此IObservable源,
IObservable(其他)
{
返回可观察的延迟(()=>
{
对象锁定对象=新对象();
Stack skipStack=新堆栈();
订阅(x=>{lock(lockObject){skipStack.Push(x);});
返回源。其中(=>
{
锁(lockObject);
{
如果(skipStack.Count>0)
{
skipStack.Pop();
返回false;
}
其他的
{
返回true;
}
}
});
});
}
然后,您的代码会像这样更新(请参阅下面的注释):
INotifyPropertyChanged源;
INotifyPropertyChanged目标;
//请参阅我答案底部的链接
var sourcePropertyChanged=source.GetPropertyChangeValues(x=>x.SourceProperty);
//单位为Rx的“无效”
var targetChangedLocaly=新主题();
var targetPropertyChanged=target.GetPropertyChangeValues(x=>x.TargetProperty)
.SkipWhen(目标变化局部);
sourcePropertyChanged
.TakeUntil(targetPropertyChanged)
.ObserveOnDispatcher()
.Subscribe(=>
{
targetChangedLocally.OnNext();
/*为targetPropertyName引发target.PropertyChanged*/
});
注意:我最近写了一篇博客;请随意窃取该代码。没有内置的方法,但您可能可以使用
Where
扩展方法过滤出事件,以便于观察。要过滤的条件是事件的发送者。我想target.PropertyChanged
事件的发送者与另一个源引发的PropertyChanged
事件的发件人
我不完全确定这是否是一种您可以使用的方法。以这种方式使用锁是可以的。锁的寿命很短,不会调用用户代码。您所说的“操作属性更改通知”是什么意思?什么操作?@Ronald我更新了我的解释,希望能更清楚一点,但我所说的操作是功能esn不返回值。
/*表示的部分为targetPropertyName*/
引发target.PropertyChanged。这是一个非常好的解决方案。不幸的是,我使用的是Silverlight,所以我没有可用的ConcurrentStack,我不想为此实现它。我已经更新了标记以显示SL。@Bryan-这不是问题。替换ConcurrentStack with Stack,并在GetPropertyChangeValues
和SkipWhen
之间添加ObserveOnDispatcher
,或者-执行您自己的锁定。我已经通过回复更新了后者(因为它以后不太可能咬到您)Doh!谢谢。有些时候起床是不划算的。不幸的是,无论哪个班级正在引发PropertyChanged
事件,发送者都将是,在这种情况下,target
,无论发生什么事情导致事件被引发。仅供参考-这应该是对我答案的评论,而不是答案本身:)
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*/
});