【问题标题】:How to use CanExecute with Mvvmcross如何将 CanExecute 与 Mvvmcross 一起使用
【发布时间】:2012-10-08 17:44:06
【问题描述】:

我有一个按钮

<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 是方法还是属性?

标签: c# data-binding xamarin.android mvvmcross


【解决方案1】:

要了解如何使用 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 问题),它们会得到解决...


就个人而言...我不倾向于使用CanExecute - 我倾向于使用单独的布尔属性,然后我将其绑定到控件上可用的任何属性 - 例如大多数控件都有EnabledIsEnabledDisabledIsDisabled 等。

我通常发现设置布尔属性比调用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 错误。

【讨论】:

  • 我认为不使用内置功能是个坏主意。您使用布尔值的方法给代码库增加了很多混乱。
  • 是的...但你不是必须为 MonoDroid 和 MonoTouch 编写所有绑定的人 :)
  • 对不起,我不明白那个评论:-)
  • 重要的一点是用户可以在 WP7、Win8、iOS 和 Droid 上共享他们的 ViewModel。 mvvmcross 怪癖可能会增加一点混乱,但总比为每个平台单独编写代码要好:)
  • @Stuart:我想知道您是否仍然(如 2014 年 12 月)建议使用单独的 IsEnabled 布尔属性与 CanExecute()?
【解决方案2】:

要跟进 Stuart 的回答,很容易同时支持 ICommand.CanExecute 以及公开属性以支持 Android 和 iOS Mvx 绑定。

为此,请将典型的CanExecute() 方法转换为属性,然后将处理程序添加到CanExecuteChanged,该处理程序在关联属性上调用RaisePropertyChanged。然后像往常一样使用RaiseCanExecuteChangedPropertyChanged 事件也会被触发。

    ...

    // constructor
    public SomeClass()
    {

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

    public bool CanDoSomething
    {
        get { ... }
    }

    ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2015-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多