如何在Mvvmcross中使用CanExecute

10

我有一个按钮

<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;

但是没有设置属性,那么怎么做呢?


UsbConnected 是一个方法还是一个属性? - Daniel Hilgarth
2个回答

8
要了解如何使用CanExecute,可以参考Silverlight或WPF - 有很多博客介绍如何使用ICommand - 例如http://weblogs.asp.net/nmarun/archive/2009/12/02/using-icommand-silverlight-4.aspxhttp://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 issues告诉我,问题将会得到解决...


个人而言...我不太喜欢使用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方法具有优势 - 因为它将命令逻辑都放在一个对象中,并且因为它可以用于防止RelayCommand内发生Execute调用。这就是为什么当我们发现它们时,我很高兴尝试修复mvvmcross绑定中的CanExecute错误。


1
我认为不使用内置功能是一个不好的想法。你使用布尔值的方法给代码库增加了很多混乱。 - Daniel Hilgarth
2
是的...但你不是那个必须为MonoDroid和MonoTouch编写所有绑定的人 :) - Stuart
2
重要的是用户可以在WP7、Win8、iOS和Droid之间共享他们的ViewModels。mvvmcross的一些小问题可能会增加一些混乱,但这比为每个平台单独编写代码要好 :) - Stuart
我也修改了我的答案 - 我完全同意使用 RaiseCanExecuteChanged 是更好的方法 - 但是如果用户不想修复错误或等待我修复它们,解决方法仍然存在。谢谢并再次道歉 :) - Stuart
5
@Stuart: 我想知道您是否仍然建议使用单独的IsEnabled布尔属性而不是CanExecute()? - Johannes Rudolph
显示剩余4条评论

5
为了跟进Stuart的回答,支持和暴露属性以支持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 { ... }
    }

    ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接