【问题标题】:ReactiveUI: Using CanExecute with a ReactiveCommandReactiveUI:将 CanExecute 与 ReactiveCommand 一起使用
【发布时间】:2011-07-19 22:34:33
【问题描述】:

我开始在 Silverlight 项目中使用 ReactiveUI 框架,在使用 ReactiveCommands 时需要一些帮助。

在我的视图模型中,我有一些大致如下所示的东西(这只是一个简化的示例):

public class MyViewModel : ReactiveObject
{
  private int MaxRecords = 5;

  public ReactiveCommand AddNewRecord { get; protected set; }

  private ObservableCollection<string> _myCollection = new ObservableCollection<string>();
  public ObservableCollection<string> MyCollection
  {
    get
    {
      return _myCollection;
    }

    set
    {
      _myCollection = value;
      raiseCollectionChanged("MyCollection");
    }
  }

  MyViewModel()
  {
    var canAddRecords = Observable.Return<bool>(MyCollection.Count < MaxRecords);
    AddNewRecord = new ReactiveCommand(canAddRecords);

    AddNewRecord.Subscribe(x => 
    {
       MyCollection.Add("foo");
    }
  }
}

canAddRecords 函数在首次创建 ReactiveCommand 时得到评估,但在将项目添加到 MyCollection 时不会重新评估它。谁能告诉我一个很好的例子,说明如何绑定ReactiveCommandcanExecute 属性,以便在这种情况下自动重新评估它?

【问题讨论】:

    标签: silverlight mvvm system.reactive reactiveui


    【解决方案1】:

    实际上,有一个更好的方法可以做到这一点,将 ObservableCollection 更改为 ReactiveCollection(它继承自 ObservableCollection,但添加了一些额外的属性):

    MyCollection = new ReactiveCollection<string>();
    
    AddNewRecord = new ReactiveCommand(
        MyCollection.CollectionCountChanged.Select(count => count < MaxRecords));
    

    现在的问题是,您不能覆盖 MyCollection,只能重新填充它(即 Clear() + Add())。让我知道这是否会破坏交易,尽管需要更多工作,但也有办法解决这个问题。

    【讨论】:

    • 我唯一的另一个要求是我需要 Observable 集合中的记录不断地按 3 个不同的字段排序。因此,当添加新记录时,集合会自动重新排序。不过,我不确定这是一个完全不同的问题。
    • 您能解释一下为什么这种方法更好吗?我不是在批评,我只是 Reactive 的新手,任何其他信息都会有所帮助。
    • 因此,当您使用 .Create 时,就像 RelayCommand - CanExecute 必须由 Silverlight 轮询。使用普通的构造函数意味着只要 很快 收集计数发生变化,CanExecute 就会正确更新(通过 CanExecuteChanged)并且按钮会立即变为灰色/不灰色。
    • 如果你正在做排序,最好通过 Collection View 的东西来做 - 如果这不可能,你可以通过 Output 属性来做,但你必须重建收集每个更改。
    • 看起来当您使用您建议的方法创建 ReactiveCommand 时,canExecute 检查直到 MyCollection 更改后才会发生。所以它不适用于我只希望命令在最初MyCollection.Count &gt; 0 时可执行的情况。一旦MyCollection 更改,它就会按预期工作。对这种情况有什么建议吗?
    【解决方案2】:

    我终于想通了。使用 ReactiveCommand.Create() 适合我的情况。

    MyViewModel()
    {
      AddNewRecord = ReactiveCommand.Create(x => MyCollection.Count < MaxRecords);
    
      AddNewRecord.Subscribe(x => 
      {
         MyCollection.Add("foo");
      }
    }
    

    【讨论】:

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