ReactiveCommand с комбинированными критериями для CanExecute
Я только начал с 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; }
}
Я хотел бы разрешить выполнение команды, если выполняются следующие критерии:
- Свойство ShareText не является нулевым или пустым
- Коллекция 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: Использование CanExecute с ReactiveCommand
Исходя из этого, я попробовал следующее:
var accountsSelected = SelectedAccounts.CollectionCountChanged.Select(count => count > 0);
ShareCommand = new ReactiveCommand(accountsSelected);
Это работает для второй части моих критериев выполнения, потому что, как только элементы добавляются или удаляются из коллекции, кнопка, подключенная к команде, включается или отключается правильно.
Мой вопрос: как мне теперь совместить это с проверкой того, что свойство ShareText не является нулевым или пустым?
Я больше не могу использовать метод this.WhenAny(..), так как переменная accountSelected не является свойством.
Спасибо
2 ответа
Использование WhenAny с IObservable
это немного сложно. Вот как бы я это сделал:
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(...);
вышеупомянутое утверждение все еще будет работать, тогда как вышеупомянутое будет все еще слушать старую коллекцию.
Я считаю, что есть разные способы получить ожидаемый результат, и это только один из способов.
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);