Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Rx:忽略由订阅者引起的更新_C#_Silverlight_Silverlight 4.0_System.reactive - Fatal编程技术网

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*/
    });