I have a Button
<Button
android:id="@+id/ButtonConnect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Disconnect"
local:MvxBind="{'Click':{'Path':'DisconnectCommand'}}" />
And I have a Command for it
public IMvxCommand DisconnectCommand
{
get
{
return new MvxRelayCommand(this.GetService<IConnectionService>().Disconnect);
}
}
Then I want to enable/disable the DisconnectCommand using
DisconnectCommand.CanExecute(this.GetService<IConnectionService>().UsbConnected);
But thats clearly wrong (It is not working), I put the check in as a a parameter, but normally I would do
DisconnectCommand.CanExecute = someBool;
But there is no property to set, so how to go about this?
To follow up on Stuart's answer, it's easy to support both ICommand.CanExecute
along with exposing properties to support Android and iOS Mvx bindings.
To do this, convert your typical CanExecute(
) methods to properties, then add handlers to CanExecuteChanged
that calls RaisePropertyChanged
on the associated property. Then use RaiseCanExecuteChanged
as normal and the PropertyChanged
event gets fired as well.
...
// constructor
public SomeClass()
{
DoSomethingCommand = new MvxCommand(OnDoSomething, () => CanDoSomething);
DoSomethingCommand .CanExecuteChanged += (sender, args) => RaisePropertyChanged(() => CanDoSomething);
}
public bool CanDoSomething
{
get { ... }
}
...
To work out how to use CanExecute
, take a look at Silverlight or WPF - there's lots of blogs out there which talk about how to use ICommand
- e.g. http://weblogs.asp.net/nmarun/archive/2009/12/02/using-icommand-silverlight-4.aspx or http://blog.galasoft.ch/archive/2009/09/26/using-relaycommands-in-silverlight-and-wpf.aspx
An example would be something like:
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 */;
}
There is one small problem though....
CanExecute
isn't really fully implemented across all the MvxBindings across all platforms... It will work for some of them, but for some of them it won't - and I don't really know which ones at present! If you come across issues, then please let me know (via GitHub issues) and they will get fixed...
Personally... I don't tend to use CanExecute
- I tend instead to use a separate Boolean property which I then bind to whatever property is available on the control - e.g. most controls have something like Enabled
, IsEnabled
, Disabled
, IsDisabled
, etc.
I generally find it easier (and more readable) to set the Boolean property rather than to call RaiseCanExecuteChanged
e.g. I'd use something like:
<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'}}" />
You can definitely argue that the CanExecute
approach has advantages - because it keeps the Command logic all in one object, and because it can be used to prevent Execute
calls happening within the RelayCommand
. That's why I'm happy to try to fix CanExecute
bugs in mvvmcross bindings as we find them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With