2016-04-18 23 views
0

私はObs1とObs2という2つの観測値を持っています。私は、Obs1のトリガをObs2の後続のトリガを抑制したい(下の大理石図)。これはどうすればいいですか?トリガを1つのオブザーバブルで使用して別のトリガをトリガする方法

Obs1---x---x--x---- 
Obs2----yyy-yy-yyyy 
Rslt-----yy--y--yyy 

具体的には、TargetとSelectedItemの2つのプロパティを持つクラスがあります。ターゲットが設定されているときは、ターゲットのSpecialValueプロパティに基づいてSelectedItemをすぐに設定する必要があります。ユーザーは選択を変更できる必要があります。その場合、新しい値がターゲットに伝播します。 SelectedItemは、ユーザーが値を変更した場合にのみ、ターゲットに戻されます。ターゲットが設定された瞬間に値がターゲットに伝搬しています。これは私が修正しようとしている望ましくない動作です。

(SelectionViewModelはReactiveUIを活用して、私たちは、移行を支援するためにプリズムのSetPropertyメソッドを模倣。BindToPropertyは、それが言うんばかりのヘルパーメソッドです。)

sealed class SelectionViewModel 
{ 
    internal SelectionViewModel() 
    { 
     this.WhenAnyValue(x => x.Target).Where(t => t != null) 
      .Select(_ => Target.SpecialValue) 
      .BindToProperty(this, x => x.SelectedItem); 

     this.WhenAnyValue(x => x.Target).Where(t => t != null) 
      .Select(_ => this.WhenAnyValue(x => x.SelectedItem).Skip(1)) 
      .Switch() 
      .BindToProperty(this, x => Target.SpecialValue); 
    } 

    private MyClass _selectedItem; 

    public MyClass SelectedItem 
    { 
     get { return _selectedItem; } 
     set { SetProperty(ref _selectedItem, value); } 
    } 

    private ITarget _target; 

    public ITarget Target 
    { 
     get { return _target; } 
     set { SetProperty(ref _target, value); } 
    } 
} 
+0

あなたは 'BindToProperty(のコードを共有してくださいすることができます)' – aateeque

+0

それは公正な要求だが、コードはかなり長いですし、私はそれが独占的だと思うので、もしそれを共有すれば、おそらく私の膝を壊すでしょう。 – ket

+0

あなたはそれが何をしているのか記述できますか?最初のparamをsource、secondをtargetとして新しい 'Binding'を作成しますか? – aateeque

答えて

2

これは、あなたがしたい値生成:

var Obs1 = new Subject<string>(); 
var Obs2 = new Subject<string>(); 

var query = Obs2.Publish(pobs2 => Obs1.Select(x => pobs2.Skip(1)).Switch()); 

query.Subscribe(Console.WriteLine); 

Obs1.OnNext("X0"); 
Obs2.OnNext("Y0"); 
Obs2.OnNext("Y1"); 
Obs2.OnNext("Y2"); 
Obs1.OnNext("X1"); 
Obs2.OnNext("Y3"); 
Obs2.OnNext("Y4"); 
Obs1.OnNext("X2"); 
Obs2.OnNext("Y5"); 
Obs2.OnNext("Y6"); 
Obs2.OnNext("Y7"); 
Obs2.OnNext("Y8"); 

私が手:明瞭にするために

 
Y1 
Y2 
Y4 
Y6 
Y7 
Y8 
+0

完璧な、ちょうど私が必要なもの。ありがとう! – ket

0

それはあなたがやろうとしているものと思われるにありますSelectedItemIObservableによって設定されているか、ユーザーによって設定されているかを解読します。状態を共有する1つの方法は、SelectedItemTargetオブジェクトまたはユーザによって変更することによって変更されているかどうかを通知するフラグを使用している場合、私は、不思議:

sealed class SelectionViewModel 
{ 
    private bool _setByTarget = false; 

    internal SelectionViewModel() 
    { 
     this.WhenAnyValue(x => x.Target).Where(t => t != null) 
      .Select(_ => Target.SpecialValue) 
      .Do(_ => _setByTarget = true) 
      .BindToProperty(this, x => x.SelectedItem); 

     this.WhenAnyValue(x => x.Target) 
      .Where(t => t != null && !_setByTarget) 
      .Select(_ => this.WhenAnyValue(x => x.SelectedItem)) 
      .Switch() 
      .BindToProperty(this, x => Target.SpecialValue); 

     this.WhenAnyValue(x => x.Target) 
      .Where(!_setByTarget) 
      .Subscribe(_ => _setByTarget = false); 
    } 

    private MyClass _selectedItem; 

    public MyClass SelectedItem 
    { 
     get { return _selectedItem; } 
     set { SetProperty(ref _selectedItem, value); } 
    } 

    private ITarget _target; 

    public ITarget Target 
    { 
     get { return _target; } 
     set { SetProperty(ref _target, value); } 
    } 
} 

この溶液を、副作用を使用します.Doを誘発することは、副作用が悪いので良い習慣ではありません!

+0

私はDoメソッド(これはほとんどのObservable拡張メソッドの場合のようです)を認識していませんでした。私はこれを試してみてください - 副作用は、非機能性を打つ! – ket

+0

2番目の考えを与えて、私はそれがこのように動作するかどうかはわかりません。なぜなら、ObserveOn(EventLoopScheduler.Instance)を行うことができるように制御するには、私が提案したものよりももっと洗練された解決策があると思われます。 – aateeque

+0

私は他の誰かがアイデアを持っているかどうかを見るためにカップル日。そうでなければ、あなたは勝つ! – ket

関連する問題