我想创建一种基于Rx的WPF ICommand。我想要做的是通过组合任意数量的IObservable<bool>流来控制CanExecute。
我的想法是使用所有谓词的最新逻辑AND值来控制ICommand.CanExecute(object parameter)方法的实现。我不想等待所有谓词都产生结果,它应该使用其中一个源谓词流OnNexts(产生一个值)。
我在尝试解决如何连接任何谓词以导致ICommand.CanExecute产生新值时遇到了困难。
暂且不考虑ICommand的实际实现(因为我的问题更多地涉及Rx方面),有人能建议我如何连接一堆谓词(IObservable<bool>),每当创建它们的底层事物发生变化时就会产生结果,但也可以共同创建一个总布尔值,我可以订阅它。最终值将是当前谓词流值的逻辑AND。
我希望不需要订阅所有谓词流,并且希望RX中有一个很酷的运算符,我可能已经忽略了。
我知道我可以合并流,但这不完全是我想要的行为,因为那只是合并了输入流的最新值。我还知道我可以CombineLatest,但这也不完全正确,因为它只在所有组合流产生值时才会产生结果。
我想要的是将流组合在一起,以便任何更改都会通知订阅者,但我还想知道组合谓词IObservable<bool>流的逻辑AND是什么,以便我可以从这个总体组合值驱动ICommand.CanExecute。
希望这有意义。
下面是一些骨架代码(我留下了一些注释掉的代码,展示了我的Rx命令想法背后的思考过程,因为它可能有助于说明我想要实现的内容)。
我的想法是使用所有谓词的最新逻辑AND值来控制ICommand.CanExecute(object parameter)方法的实现。我不想等待所有谓词都产生结果,它应该使用其中一个源谓词流OnNexts(产生一个值)。
我在尝试解决如何连接任何谓词以导致ICommand.CanExecute产生新值时遇到了困难。
暂且不考虑ICommand的实际实现(因为我的问题更多地涉及Rx方面),有人能建议我如何连接一堆谓词(IObservable<bool>),每当创建它们的底层事物发生变化时就会产生结果,但也可以共同创建一个总布尔值,我可以订阅它。最终值将是当前谓词流值的逻辑AND。
我希望不需要订阅所有谓词流,并且希望RX中有一个很酷的运算符,我可能已经忽略了。
我知道我可以合并流,但这不完全是我想要的行为,因为那只是合并了输入流的最新值。我还知道我可以CombineLatest,但这也不完全正确,因为它只在所有组合流产生值时才会产生结果。
我想要的是将流组合在一起,以便任何更改都会通知订阅者,但我还想知道组合谓词IObservable<bool>流的逻辑AND是什么,以便我可以从这个总体组合值驱动ICommand.CanExecute。
希望这有意义。
下面是一些骨架代码(我留下了一些注释掉的代码,展示了我的Rx命令想法背后的思考过程,因为它可能有助于说明我想要实现的内容)。
public class ViewModel : INPCBase
{
private string title;
private bool hasStuff;
public ViewModel()
{
//Initialise some command with 1st predicate, and
// initial CanExecute value
//SomeCommand = new ReactiveCommand(
// this.ObserveProperty(x => x.Title)
// .Select(x => !string.IsNullOrEmpty(x)), false);
//SomeCommand.AddPredicate(this.ObserveProperty(x => x.HasStuff));
//SomeCommand.CommandExecutedStream.Subscribe(x =>
// {
// MessageBox.Show("Command Running");
// });
IObservable<bool> obsPred = this.ObserveProperty(x => x.Title)
.Select(x => !string.IsNullOrEmpty(x))
.StartWith(!string.IsNullOrEmpty(this.Title));
IObservable<bool> obsPred2 = this.ObserveProperty(x =>
x.HasStuff).StartWith(this.HasStuff);
obsPred.Merge(obsPred2).Subscribe(x =>
{
//How do I get this to fire whenever obsPred OR
//obsPred2 fire OnNext, but also get a combined value (bool)
//of the AND of obsPred & obsPred2 (bearing in mind I may
//want more than 2 predicates, it should cope with any number of
//IObservable<bool> predicates
});
}
public string Title
{
get
{
return this.title;
}
set
{
RaiseAndSetIfChanged(ref this.title, value, () => Title);
}
}
public bool HasStuff
{
get
{
return this.hasStuff;
}
set
{
RaiseAndSetIfChanged(ref this.hasStuff, value, () => HasStuff);
}
}
}