代码之家  ›  专栏  ›  技术社区  ›  Bryan Anderson

Rx:忽略订阅服务器导致的更新

  •  2
  • Bryan Anderson  · 技术社区  · 14 年前

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

    我现在的问题是我想忽略 财产变更 财产变更 事件由外部源引发。有什么好办法可以做到这一点吗?

    3 回复  |  直到 14 年前
        1
  •  4
  •   Richard Szalay    14 年前

    做你所说的事没有固定的方法。这里有一个简单的 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

        2
  •  0
  •   Ronald Wildenberg    14 年前

    没有内置的方法,但是您可以使用 Where 可观测的可拓方法。要筛选的条件将是事件的发件人。我想 target.PropertyChanged 事件不同于 PropertyChanged 其他源引发的事件。

        3
  •  0
  •   Jeffrey van Gogh    14 年前

    用这种方法在Rx中使用锁是可以的。锁是短暂的,不会调用用户代码。