假设我有两个可观察量Obs1和Obs2。我希望Obs1上的触发器能够抑制Obs2上的后续触发(下面的大理石图)。我该怎么做?
Obs1---x---x--x----
Obs2----yyy-yy-yyyy
Rslt-----yy--y--yyy
具体来说,我有一个包含两个属性的类,Target和SelectedItem。设置目标时,应立即根据目标上的SpecialValue属性设置SelectedItem。用户应该能够更改选择,在这种情况下,新值会传播回目标。仅当用户更改值时,SelectedItem才会传播回目标;但是,当目标设置时,该值会传播回目标 - 这是我正在尝试修复的不良行为。
(SelectionViewModel利用ReactiveUI,但我们模仿Prism的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 :(得分: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
答案 1 :(得分:0)
您尝试做的似乎是解密SelectedItem
是由IObservable
还是由用户设置。我想知道共享状态的一种方法是使用标志来通知SelectedItem
对象或用户的更改是否正在更改Target
,所以:
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
,这不是好习惯,因为副作用很差!