Как использовать CanExecute с Mvvmcross

у меня есть кнопка

<Button 
      android:id="@+id/ButtonConnect"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="Disconnect"
      local:MvxBind="{'Click':{'Path':'DisconnectCommand'}}" />

И у меня есть команда для этого

public IMvxCommand DisconnectCommand
{
    get
    {
        return new MvxRelayCommand(this.GetService<IConnectionService>().Disconnect);
    }
}

Затем я хочу включить/отключить DisconnectCommand, используя

DisconnectCommand.CanExecute(this.GetService<IConnectionService>().UsbConnected);

Но это явно неправильно (это не работает), я поставил галочку в качестве параметра, но обычно я бы сделал

DisconnectCommand.CanExecute = someBool;

Но свойства для установки нет, так как же это сделать?


person Mech0z    schedule 18.10.2012    source источник
comment
Является ли UsbConnected методом или свойством?   -  person Daniel Hilgarth    schedule 18.10.2012


Ответы (2)


Чтобы понять, как использовать CanExecute, взгляните на Silverlight или WPF — существует множество блогов, в которых рассказывается, как использовать ICommand — например, http://weblogs.asp.net/nmarun/archive/2009/12/02/using-icomand-silverlight-4.aspx или http://blog.galasoft.ch/archive/2009/09/26/using-relaycommands-in-silverlight-and-wpf.aspx< /а>

Примером может быть что-то вроде:

private MvxRelayCommand _disconnectCommand;
public IMvxCommand DisconnectCommand
{
    get
    {
        if (_disconnectCommand == null)
            _disconnectCommand = new MvxRelayCommand(this.GetService<IConnectionService>().Disconnect, item => this.IsItemConnected(item));
        return _disconnectCommand;
    }
}

private void SomeServiceNotificationHandler()
{
    _disconnectCommand.RaisePropertyChanged();
}

private bool IsItemConnected(object thing)
{
    return /* your code */;
}

Хотя есть одна маленькая проблема....

CanExecute на самом деле не полностью реализован во всех MvxBindings на всех платформах... Он будет работать для некоторых из них, но для некоторых нет - и я действительно не знаю, какие из них в настоящее время! Если вы столкнетесь с проблемами, дайте мне знать (через проблемы с GitHub), и они будут исправлены...


Лично... я не склонен использовать CanExecute - вместо этого я предпочитаю использовать отдельное логическое свойство, которое затем привязываю к любому свойству, доступному в элементе управления - например. большинство элементов управления имеют что-то вроде Enabled, IsEnabled, Disabled, IsDisabled и т. д.

Обычно мне проще (и читабельнее) установить логическое свойство, чем вызывать RaiseCanExecuteChanged

например Я бы использовал что-то вроде:

<Button 
  android:id="@+id/ButtonConnect"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="Disconnect"
  local:MvxBind="{'Click':{'Path':'DisconnectCommand'},'Enabled':{'Path':'UsbConnected'}}" />

Вы определенно можете утверждать, что подход CanExecute имеет преимущества, потому что он сохраняет всю логику команды в одном объекте и потому что его можно использовать для предотвращения вызовов Execute внутри RelayCommand. Вот почему я рад попытаться исправить CanExecute ошибок в привязках mvvmcross по мере их обнаружения.

person Stuart    schedule 18.10.2012
comment
Я думаю, что это плохая идея, чтобы не использовать встроенный функционал. Ваш подход с логическими значениями добавляет много беспорядка в кодовую базу. - person Daniel Hilgarth; 18.10.2012
comment
Да... но не тебе же писать все привязки для MonoDroid и MonoTouch :) - person Stuart; 18.10.2012
comment
Извините, я не понимаю этот комментарий :-) - person Daniel Hilgarth; 18.10.2012
comment
Извините - я должен знать лучше, чем делать бойкие комментарии на StackOverflow. По сути, инфраструктура MvvmCross включает библиотеки привязки для iOS и Droid — github.com/slodge/MvvmCross. /tree/vnext/Cirrious. Они охватывают многое (свойства, команды, вложенность, преобразователи и т. д.), но в них есть некоторые пробелы (неполные реализации параметров команд, поведения и т. д.). Хотя эти пробелы существуют, либо кто-то (обычно я) должен написать код для их устранения, либо пользователи должны делать свои собственные обходные пути, и htis может вызвать небольшой дополнительный беспорядок ViewModel. Извините еще раз за бойкий комментарий :) - person Stuart; 18.10.2012
comment
Важным моментом является то, что пользователи могут делиться своими ViewModels между WP7, Win8, iOS и Droid. Причуды mvvmcross могут добавить немного беспорядка, но это лучше, чем писать код отдельно для каждой платформы :) - person Stuart; 18.10.2012
comment
Я также изменил свой ответ - я согласен на 100%, что делать это с использованием RaiseCanExecuteChanged - лучший подход, но обходной путь все еще существует, если пользователь не хочет исправлять ошибки или ждать, пока я их исправлю. Спасибо и еще раз извините :) - person Stuart; 18.10.2012
comment
Я буду использовать обходной путь, я не уверен, что чувствую себя достаточно компетентным, чтобы работать с исходным кодом - person Mech0z; 18.10.2012
comment
@Stuart: Мне интересно, порекомендуете ли вы по-прежнему (как в декабре 2014 г.) использовать отдельные логические свойства IsEnabled вместо CanExecute()? - person Johannes Rudolph; 11.12.2014
comment
Документация MvvmCross ›Однако в MvvmCross это автоматическое включение/отключение привязки не в настоящее время широко не поддерживается - вместо этого поддержка предоставляется вторичным свойствам привязки - например. к парам креплений... - person SwiftArchitect; 12.11.2019

Чтобы продолжить ответ Стюарта, легко поддерживать как ICommand.CanExecute, так и раскрывать свойства для поддержки привязок Android и iOS Mvx.

Для этого преобразуйте ваши типичные CanExecute() методы в свойства, затем добавьте обработчики в CanExecuteChanged, которые вызывают RaisePropertyChanged для связанного свойства. Затем используйте RaiseCanExecuteChanged как обычно, и событие PropertyChanged также будет запущено.

    ...

    // constructor
    public SomeClass()
    {

        DoSomethingCommand = new MvxCommand(OnDoSomething, () => CanDoSomething);
        DoSomethingCommand .CanExecuteChanged += (sender, args) => RaisePropertyChanged(() => CanDoSomething);
    }

    public bool CanDoSomething
    {
        get { ... }
    }

    ...
person HolySamosa    schedule 23.08.2013