How to implement ICommand without parameters - c#

In my project, i'd like to use MVVM (& Commands). I've started learning about commands and implementation of ICommand.
I'd like to create implementation of ICommand without parameters.
(To trigger loading of data/flushing of data etc. - I don't need any parameters to do it, so it just seems natural to try and create command without parameters)
This is the code I'm using:
using System.Windows.Input;
public class NoParameterCommand : ICommand
{
private Action executeDelegate = null;
private Func<bool> canExecuteDelegate = null;
public event EventHandler CanExecuteChanged = null;
public NoParameterCommand(Action execute)
{
executeDelegate = execute;
canExecuteDelegate = () => { return true; };
}
public NoParameterCommand(Action execute, Func<bool> canExecute)
{
executeDelegate = execute;
canExecuteDelegate = canExecute;
}
public bool CanExecute()
{
return canExecuteDelegate();
}
public void Execute()
{
if (executeDelegate != null)
{
executeDelegate();
}
}
}
But i got errors about not implementing the ICommand interface in the right manner
('XXX.YYYY.NoParameterCommand' does not implement interface member 'System.Windows.Input.ICommand.Execute(object)')
So I thought about doing it like this instead:
(Added the parameters that were missing from CanExecute and Execute)
public class NoParameterCommand : ICommand
{
...omitted - no changes here...
public bool CanExecute(object parameter) //here I added parameter
{
return canExecuteDelegate();
}
public void Execute(object parameter) //and here
{
if (executeDelegate != null)
{
executeDelegate();
}
}
}
IS THIS A GOOD WAY TO DO IT?
SHOULD I USE ANOTHER WAY? (IF SO, WHAT SHOULD I DO INSTEAD?)

This is a good way to do it.
No, you should not use another way.
Additional suggestions:
Thinking about this again, I would improve your architecture by introducing an additional hierarchy level where CanExecute() and Execute() are abstract. From that class, derive your command class that invokes delegates.
This way, you can decide later on whether you want to supply your logic for your parameterless commands via delegates or via subclassing your base command class.

I'm not really sure what your concern is. It is common to ignore the parameters in the ICommand interface.
If you really want CanExecute and Execute methods that don't have parameters, you can implement the interface explicitly (rather than implicitly). The ICommand methods will still exist, but to anyone looking at your object from the outside, they won't be able to see those methods:
bool ICommand.CanExecute(object parameter) { this.CanExecute(); }
public bool CanExecute()
{
//do work
}
You are essentially hiding the interface implemenation. If someone wants to directly call the CanExecute method from the interface, they would have to type cast to ICommand in order to do it. You really don't gain anything in doing it this way, but if you are concerned with how your class looks to outside developers (e.g. you are developing an API), then this can make it look a little cleaner as you are letting them know you do not require any parameters.

I personally prefer it this way:
public class MyCommand : ICommand
{
private static bool True() { return true; }
private readonly Action _execute;
private Func<bool> _canExecute;
private Func<bool> _isVisible;
public event EventHandler IsVisibleChanged;
public event EventHandler CanExecuteChanged;
public MyCommand(Action execute, Func<bool> canExecute = null, Func<bool> isVisible = null)
{
_execute = execute;
_canExecute = canExecute ?? True;
_isVisible = isVisible ?? True;
}
public void Execute()
{
_execute();
}
public Func<bool> CanExecute
{
set
{
_canExecute = value ?? True;
CanExecuteChanged(this, new EventArgs());
}
get { return _canExecute; }
}
public Func<bool> IsVisible
{
set
{
_isVisible = value ?? True;
IsVisibleChanged(this, new EventArgs());
}
get { return _isVisible; }
}
bool ICommand.CanExecute(object parameter)
{
return CanExecute();
}
void ICommand.Execute(object parameter)
{
Execute();
}
}
However, since the delegates usually don't change, I prefer an immutable version:
[ImmutableObject(true)]
public class MyImmutableCommand : ICommand
{
private static bool True() { return true; }
private readonly Action _execute;
private readonly Func<bool> _canExecute;
private readonly Func<bool> _isVisible;
[Obsolete("Will not be invoked, because the implementation never changes.")]
public event EventHandler CanExecuteChanged;
public MyImmutableCommand(Action execute, Func<bool> canExecute = null, Func<bool> isVisible = null)
{
_execute = execute;
_canExecute = canExecute ?? True;
_isVisible = isVisible ?? True;
}
public bool CanExecute()
{
return _canExecute();
}
public bool IsVisible()
{
return _isVisible();
}
public void Execute()
{
_execute();
}
bool ICommand.CanExecute(object parameter)
{
return CanExecute();
}
void ICommand.Execute(object parameter)
{
Execute();
}
}

Related

Async ICommand implementation

I'm facing a strange behavior by my asny ICommand implementation when I tried to disable the command while it's executing by default (even when no CanExecute predicate was passed to it).
public bool CanExecute(object parameter)
{
if (CanExecutePredicate == null)
{
return !mIsExecuting;
}
return !mIsExecuting && CanExecutePredicate(parameter);
}
public async void Execute(object parameter)
{
mIsExecuting = true;
await ExecuteAsync(parameter);
mIsExecuting = false;
}
I tried to introduce a private bool, which I set to true just before executing and to false afterwards. When execution is finished the bool is set, but CanExecute is only called after I click a mousebutton or move the mouse or w/e.
Now I tried to call
CanExecute(null);
after
mIsExecuting = false;
but that doesn't help neither. I dont know what I'm missing.
Thanks for your help
EDIT:
To clarify I add the constructors for this class aswell:
public AsyncRelayCommand(Func<object, Task> execute)
: this(execute, null)
{
}
public AsyncRelayCommand(Func<object, Task> asyncExecute,
Predicate<object> canExecutePredicate)
{
AsyncExecute = asyncExecute;
CanExecutePredicate = canExecutePredicate;
}
protected virtual async Task ExecuteAsync(object parameter)
{
await AsyncExecute(parameter);
}
In async scenarios, WPF tends not to know when to check CanExecute, that's why you have the "CanExecuteChanged" event in the Icommand interface.
You should have something like this in your command implementation:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
With the code above you can now do this:
public async void Execute(object parameter)
{
mIsExecuting = true;
RaiseCanExecuteChanged ( ); // Not necessary if Execute is not called locally
await ExecuteAsync(parameter);
mIsExecuting = false;
RaiseCanExecuteChanged ( );
}
This will tell WPF you want to refresh the CanExecute state of command.

RelayCommand and delegates, trying to understand delegates

I need some help to understand what delegates is, and if I have used it in my program. I'm using the RelayCommand class which I found in another stack post to implement my commands.
RelayCommand:
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Func<bool> _canExecute;
public RelayCommand(Action<object> execute, Func<bool> canExecute = null)
{
if (execute == null)
throw new ArgumentNullException(nameof(execute));
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute.Invoke();
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
In my ViewModel's constructor, I am doing this:
public ICommand SearchCommand { get; set; }
//Constructor
public BookingViewModel()
{
SearchCommand = new RelayCommand(SearchCommand_DoWork, () => true);
}
public async void SearchCommand_DoWork(object obj)
{
//Code inside this method not shown
}
I know that a delegate is a type that encapsulate a method. You can write a delegate like this:
public delegate int MethodName(string name)
Where the delegate is encapsulating the method MethodName that has a return type of int and takes a parameter of a string.
Does this mean that there is a delegate created when using ICommand like i shown in the code? Where the encapsulating method is "SearchCommand_DoWork"
Hope some one can clear some things out for me.
Does this mean that there is a delegate created when using ICommand like i shown in the code? Where the encapsulating method is "SearchCommand_DoWork"
You're creating a new object of type RelayCommand. As you can see in the class' constructor, you're passing in an Action object (delegate that returns no value) and a Func object (delegate that returns a value).
For the Action delegate you're passing in an object that encapsulates the void function SearchCommandDoWork, for the Func object you're passing in an lambda function that takes no parameter and always returns true.
The Action delegate encapsulates your SearchCommand_DoWork function (a delegate is basically a type safe function pointer).
Both Action and Func are predefined delegates. You can also define your own delegates, which is what
public delegate int MethodName(string name)
does.

redundant ICommand class for wpf mvvm

I'm still learning about wpf, however I'm familiar withe how to setup mvvm in wpf c#. However when it comes to the ICommand/RelayCommand stuff, its a bit of a confusing area for me. Over the past few months I've compiled a few implementations of the ICommand classes in order to create my tools. However I'm at the point now where I've read a few articles and I've looked at the code long enough, I'm looking for someone to help me out and put into simple terms what is going on here and if so, how can I combine/clean up these classes. At the moment the code seems redundant and I'm not sure how to go about optimizing it. Hope this isn't asking for to much. Thanks.
The two important things I want to maintain in this, is the ability to pass arguments to the commands as seen in this first usage example of RelayCommand. Secondly the ability to enable/disable a command as seen in the second command.
So in my tool i have this helper class.
1. I don't get the differences of use between the two classes inside this RelayCommand.cs. There is a public and an internal class.
2. Is there a need for both or can they be combine?
RelayCommand.cs
using System;
using System.Windows.Input;
namespace WpfApplication1.Helper
{
public class RelayCommand<T> : ICommand
{
private readonly Action<T> execute;
private readonly Predicate<T> canExecute;
public RelayCommand(Action<T> execute, Predicate<T> canExecute = null)
{
if (execute == null)
throw new ArgumentNullException("execute");
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (parameter == null)
{
return true;
}
else
{
return canExecute == null || canExecute((T)parameter);
}
}
public void Execute(object parameter)
{
execute((T)parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
// added
internal class RelayCommand : ICommand
{
private readonly Predicate<object> canExecute;
private readonly Action<object> execute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
if (execute == null)
throw new ArgumentNullException("execute");
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute == null || canExecute(parameter);
}
public void Execute(object parameter)
{
execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
An example of me using the RelayCommand.cs in my class object called Customer.cs
private ICommand addNewLicense_Command;
public ICommand AddNewLicense_Command
{
get
{
return addNewLicense_Command ?? (addNewLicense_Command = new RelayCommand<Customer>(n =>
{
AddNewLicense_Execute(n);
}));
}
}
So then in my MainViewModel.cs i have another ICommand Class in the same project my Helper class mentioned above is part of. Is this class necessary? It seems so similar to the RelayCommand class.
public class CommandHandler : ICommand
{
private Action _action;
private bool _canExecute;
public CommandHandler(Action action, bool canExecute)
{
_action = action;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_action();
}
}
An example of me using CommandHandler in my MainViewModel.cs
private ICommand addNewUser_Command;
public ICommand AddNewUser_Command
{
get
{
return addNewUser_Command ?? (addNewUser_Command = new CommandHandler(() => AddNewUser_Execute(), true));
}
}
If you use a library like MVVM Lite then it will provide the RelayCommand implementations for you. Either way use the non-generic when you don't need a parameter passed in e.g. an "Ok" button:
public ICommand OkCommand { get { return new RelayCommand(Ok); } }
protected virtual void Ok()
{
// ... do something ...
}
The associated XAML is something like:
<Button Content="Ok" Command="{Binding OkCommand}" IsDefault="True" />
Use the generic when you want to pass a parameter:
public ICommand OpenClientCommand { get { return new RelayCommand<Client>(OnOpenClient); } }
private void OnOpenClient(Client client)
{
// ... do something with client ...
}
In this case you need to pass in a Client object via the command parameter:
<Button Content="Open" Command="{Binding OpenClientCommand}" CommandParameter="{Binding SelectedClient}"/>
Passing parameters is also handy when used with event triggers, e.g. you can add something like this to intercept your MainWindow's Closing event:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<cmd:EventToCommand Command="{Binding ClosingCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
This trigger passes the message arguments into your handler which gives you the opportunity to cancel it in the event that the user hasn't saved their changes:
public ICommand ClosingCommand { get { return new RelayCommand<CancelEventArgs>(OnClosing); } }
private void OnClosing(CancelEventArgs args)
{
if (!PromptUserForClose())
args.Cancel = true;
}
The RelayCommand you have is all you need. If you want to disable the command you can pass a method in the constructor do do so:
return addNewLicense_Command ?? (addNewLicense_Command = new RelayCommand<Customer>(n =>
{
AddNewLicense_Execute(n);
},AllowAddNeLicense));
...
bool AllowAddNewLicense()
{
return _allowAddEnabled;
}
The second class called CommandHandler is just another implementation of ICommand. The difference is that you can pass the "enabled" boolean inside the constructor, which means it will remain the same unless you create a new instance of it. While in the RelayCommand you can pass a function that gets executed everytime* so you can influence the outcome.

Simple way to create a command

I am new to C# and I need to create simple binding command for one button. I have been reading a lot of articles for last hours but it simply got me more confused.
I have an WPF window (let's say Window1) where I have button "AddCustomer". What is the simplest way to create command for it? (By simplest I mean easy to understand)
In every article they were doing it differently. I need you to show me also how to bind it in xaml, more detailed the better... like I said, I am new.
Thank you for your help.
below is the complete solution for commands in WPF.
first create a class for execute the command.
public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
private Action<object> _action;
private bool _canSave;
public RelayCommand(Action<object> execute) : this(execute, null) { }
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null) throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public RelayCommand(Action<object> action, bool CanSave)
{
this._action = action;
this._canSave = CanSave;
}
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
below is the ViewModel
public FilterViewModel()
{
private RelayCommand _commandSave;
public ICommand Save
{
get {
return _commandSave ?? (_commandSave =
new RelayCommand(param => SaveMethod(param), CanSave));
}
}
private void SaveMethod
{
//code for save
}
private Predicate<object> CanSave
{
get { return o => true; }
}
}
and finally using the command in XAML.
<Button x:Name="btnSave" Content="Save" Command="{Binding Save}" CommandParameter="PASS-PARAMETER-HERE" ></Button>
Here's my take on it, the following is 'simplest' because you are leveraging the Prism library and so the amount of code you write is small. Use the nuget manager to add Prism to your project if you're not already using it ...
The xaml:
<Button Command="{Binding AddCustomerCommand}" Content="Add Customer"/>
In your viewmodel:
(1) Declare your command:
public ICommand AddCustomerCommand{ get; private set; }
(2) Define your command:
AddCustomerCommand= new DelegateCommand(AddCustomer);
(3) And create the method:
private void AddCustomer()
{
//do your logic here
}
Extended version:
You can pass a parameter from the xaml:
<Button Command="{Binding AddCustomerCommand}" CommandParameter={Binding SelectedItem, ElementName=MySelectorThingy} Content="Add Customer"/>
Remember to change the signature of your delegate and method:
AddCustomerCommand= new DelegateCommand<WhateverMyTypeIs>(AddCustomer);
private void AddCustomer(WhateverMyTypeIs selectedThing)
{
//do your logic here
}
You can also define in the DelegateCommand when the button should be available (CanExecute), like the following:
public DelegateCommand AddCustomerCommand{ get; private set; }
AddCustomerCommand = new DelegateCommand(AddCustomer, AddCustomer_CanExecute);
And then define the method for deciding whether you can execute or not:
private bool AddCustomer_CanExecute()
{
if (DateTime.Now.DayOfWeek.Equals(DayOfWeek.Monday))
return true;
else
return false;
}

How can I use a routed command on the view from a view model

I am trying to use a RoutedCommand on my view so that I can use the CanExecute functionality, but the only way I can get it to work is with a DelegateCommand from Prism. When I try to use the RoutedCommand the button stays inactive and the CanExecute function never gets used.
I've tried putting a CommandBinding on my XAML but that gives a "Only instance methods on the generated or code-behind class are valid." error. Here is that code:
<Window.CommandBindings>
<CommandBinding Command="AddCommand"
Executed="my:SettingsDialogViewModel.AddCommandMethod"
CanExecute="my:SettingsDialogViewModel.AddCommandMethodCanExecute" />
</Window.CommandBindings>
I've also tried setting up a CommandBinding in code, but that doesn't help either. I'm just not sure how to get it to work, short of sticking it in the code-behind, or implementing some ridiculously complicated looking thing I've found on the web.
Thanks for any help :)
EDIT:
Here are the methods I am trying to use:
public void AddCommandMethod()
{
if (SelectedMain != null)
{
SelectedMain.IsDirty = true;
_faveAppList.Add(SelectedMain);
SelectedMain.ListOrder = _faveAppList.Count;
_mainAppList.Remove(SelectedMain);
_listDirty = true;
}
}
public void AddCommandMethodCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
That isn't the proper MVVM notation. I'll provide one way of doing this.
// MyView.cs
public class MyView : UserControl
{
public MyViewViewModel ViewModel
{
get { return (MyViewViewModel) DataContext;}
set { DataContext = value; }
}
}
// DelegateCommand.cs
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public DelegateCommand(Action<object> execute)
: this(execute, null) {}
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public override bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public override void Execute(object parameter)
{
_execute(parameter);
}
}
// MyViewViewModel.cs
public class MyViewViewModel
{
public ICommand AddCommand {get;set;}
public MyViewViewModel()
{
AddCommand = new DelegateCommand (AddCommandMethod, AddCommandMethodCanExecute);
}
private void AddCommandMethod (object parameter)
{
}
private bool AddCommandMethodCanExecute(object parameter)
{
// Logic here
return true;
}
}
// MyView.xaml
<Button Command="{Binding AddCommand}" />
A better option would be to implement the ICommand interface and write your logic in the implemented methods. Then your view model can return your custom command and you could just bind to it from your view.
This will separate the actual command implementation from your view model but you can still nicely implement the logic within your view model.
Something like this:
public abstract class BaseCommand : ICommand
{
// needed to connect to WPF's commanding system
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public abstract bool CanExecute(object parameter);
public abstract void Execute(object parameter);
}
public class AddCommand : BaseCommand
{
private readonly MyViewModel _vm;
public AddCommand(MyViewModel vm)
{
this._vm = vm;
}
public override bool CanExecute(object parameter)
{
// delegate back to your view model
return _vm.CanExecuteAddCommand(parameter);
}
public override void Execute(object parameter)
{
_vm.ExecuteAddCommand(parameter);
}
}
public class MyViewModel
{
public ICommand AddCommand { get; private set; }
public MyViewModel()
{
AddCommand = new AddCommand(this);
}
public bool CanExecuteAddCommand(object parameter)
{
}
public void ExecuteAddCommand(object parameter)
{
}
}
Then just bind controls that issues the command.
<Button Command="{Binding AddCommand}">...</Button>

Categories

Resources