【问题标题】:ReactiveCommand with combined criteria for CanExecute具有 CanExecute 组合标准的 ReactiveCommand
【发布时间】:2013-03-18 10:03:07
【问题描述】:

我刚刚开始使用 ReactiveUI。我有以下课程:

public class MainViewModel : ReactiveObject, IRoutableViewModel 
{
   private string shareText;

   public ReactiveCollection<SharingAccountViewModel> SelectedAccounts { get; private set; }

   public string ShareText 
   { 
      get { return shareText; }
      set
      {
          this.RaiseAndSetIfChanged(ref shareText, value);
      }
   }

   public IReactiveCommand ShareCommand { get; private set; }
}

我想做的是在满足以下条件时允许命令执行:

  1. ShareText 属性不为 null 或为空
  2. SelectedAccounts 集合至少包含一个值

我尝试了以下方法,但它不起作用,因为连接到命令的按钮永远不会启用:

ShareCommand = new ReactiveCommand(this.WhenAny(viewModel => viewModel.ShareText,
  viewModel => viewModel.SelectedAccounts,
  (x, y) => !String.IsNullOrEmpty(x.Value) && y.Value.Count > 0));

如果我只是检查 ShareText 属性,它可以正常工作:

  ShareCommand = new ReactiveCommand(this.WhenAny(viewModel => viewModel.ShareText,
            (x) => !String.IsNullOrEmpty(x.Value)));

我看了ReactiveUI: Using CanExecute with a ReactiveCommand问题的答案

基于此,我尝试了以下方法:

var accountsSelected = SelectedAccounts.CollectionCountChanged.Select(count => count > 0);
ShareCommand = new ReactiveCommand(accountsSelected);

这适用于我的执行标准的第二部分,因为一旦从集合中添加或删除项目,与命令挂钩的按钮就会正确启用或禁用。

我的问题是我现在如何将它与检查 ShareText 属性是否为空或为空相结合?

我不能再使用 this.WhenAny(..) 方法,因为 accountsSelected 变量不是属性。

谢谢

【问题讨论】:

    标签: c# system.reactive reactiveui


    【解决方案1】:

    使用带有IObservable 的WhenAny 有点棘手。以下是我的做法:

    var canShare = Observable.CombineLatest(
        this.WhenAnyObservable(x => x.SelectedAccounts.CollectionCountChanged),
        this.WhenAny(x => x.ShareText, x => x.Value),
        (count, text) => count > 0 && !String.IsNullOrWhitespace(text));
    

    WhenAnyObservable 在这里的优势在于,如果您决定重新分配 SelectedAccounts(即SelectedAccounts = new ReactiveCollection(...);,上述语句仍然有效,而上述语句仍然在听旧的收藏。

    【讨论】:

    • 谢谢保罗。我喜欢你的解决方案,因为它更紧凑,更容易让我理解。试图让我的头脑围绕 Rx ......爱你在 ReactiveUI 上的工作 btw
    【解决方案2】:

    我相信有不同的方法可以得到预期的结果,这只是一种方法。

    var canExecute = this.ObservableForProperty(v => v.ShareText)
                             .Select(_ => Unit.Default)
                      .Merge(SelectedAccounts.CollectionCountChanged
                                         .Select(_ => Unit.Default))
                      .Select(_ => !String.IsNullOrEmpty(ShareText)
                                        && SelectedAccounts.Any())
                      .StartWith(false);
    
    ShareCommand = new ReactiveCommand(canExecute);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-17
      • 1970-01-01
      • 1970-01-01
      • 2020-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多