RelayCommand and delegates, trying to understand delegates - c#

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.

Related

The event 'Command.CanExecuteChanged' can only appear on the left hand side of += or -=

Am I missing something in my Command-ViewModel?
public class Command : ICommand
{
public Command(Action execute, Func<bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute ?? new Func<bool>(() => true);
}
private Action execute;
private Func<bool> canExecute;
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return canExecute.Invoke();
}
public void Execute(object parameter)
{
execute?.Invoke();
}
}
Everytime I want to use CanExecuteChanged in my MainViewModel with this line of code ((Command)MyCommand).CanExecuteChanged(); it gives me this error The event 'Command.CanExecuteChanged' can only appear on the left hand side of += or -=
CanExecuteChanged is an event. You can only use it like this:
YourCommand.CanExecuteChanged += (sender, args) =>
{
// Do your magic here
};
public event EventHandler CanExecuteChanged;
is syntactic sugar. What the compiler actually generates when you put this in is something like*
private EventHandler _CanExecuteChanged;
public event EventHandler CanExecuteChanged
{
add { _CanExecuteChanged += value; }
remove { _CanExecuteChanged -= value; }
}
So the CanExecuteChange that's publicly exposed isn't the actual field but only something you can add and remove handlers with.
Related note: The backing field being private is also the reason for the normal pattern of having a protected OnXXXX() method in the base class.
public event EventHandler CanExecuteChanged;
protected void OnCanExecuteChanged(EventArgs args)
{
CanExecuteChanged?.Invoke(this, args);
}
*Note the "like" part; there's some null checking that's needed for proper add and remove as well.
To answer your question yes you are missing something from your code. I can't tell if you are using the Command class supplied by Xamarin.Forms but if you aren't then you really should be!
Ultimately you cannot interact with an event outside of the class that it belongs to apart from subscribing for the event notification which is what the 'The event 'Command.CanExecuteChanged' can only appear on the left hand side of += or -=' is telling you. To subscribe you implement something like the following:
MyCommand.CanExecuteChanged += (sender, e) =>
{
// Your code to react to the event goes here.
};
What you can do though and this is where you need to be using the Xamarin.Forms Command class (or you can implement something similar yourself in your Command class). Is call ChangeCanExecute e.g.
((Command)MyCommand).ChangeCanExecute();
This will then trigger the event to be fired and thus updating any UI controls that are bound to that command.
I deleted my Command-Class and now I am using the Xamarin.Forms Command Class which is making this a lot easier because now I can just use this delicious short line of code: ((Command)MyCommand).ChangeCanExecute(); to fire the event.
Thanks to all of you guys.
Just a another approach!
public sealed class Command : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public RelayCommand(Predicate<object> CanExecute, Action<object> Execute)
{
_canExecute = CanExecute;
_execute = Execute;
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
Then just let the Command Manager handle updating your .CanExecuteChanged problem :)
If you need to force the Command Manager to "look again" call CommandManager.InvalidateRequerySuggested();
Here is a little more info on the Command Manager
How does CommandManager.RequerySuggested work?

WPF View and ModelView creating

I'am distracted because of view and modelview objects instantiating. As an example:
I've got view V with a listview LV and a button. To the button is bound command that takes as a parametr listview LV. Commands CanExecute method checks whether listView LV has elements. But when i open view V the view model object creates before the view V does. So when CanExecture method checks a listView, it is null and my button becomes unavaliable for ever.
How solve that problem?
EDIT:
Command implementation:
public class DelegateCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
if (execute == null)
{
throw new ArgumentNullException(nameof(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 void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
For that kind of command implementation, you have to call RaiseCanExecuteChanged() manually (in your case after the list view got items).
You can also change the implementation of the CanExecuteChanged event to:
[...]
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
[...]
That implementation enbales the command manager to evaluate CanExecute automatically.

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.

Make Command's CanExecute depend on other field's value

I'm working on a small WPF MVVM application. In essence, the user browses for a file, then clicks "Execute" to run some code on the file.
In my view model class, I've bound the two button clicks ("Browse" and "Execute") to an ICommand.
internal class DelegateCommand : ICommand
{
private readonly Action _action;
public DelegateCommand(Action action)
{
_action = action;
}
public void Execute(object parameter)
{
_action();
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
internal class Presenter : INotifyPropertyChanged // VM class
{
private string filePath;
public string FilePath
{
get { return filePath; }
set
{
filePath = value;
RaisePropertyChangedEvent("FilePath");
}
}
public ICommand ExecuteCommand
{
// returns a DelegateCommand
}
public ICommand BrowseCommand
{
// how to enable/disable button based on whether or not a file has been selected?
}
}
Here, CanExecute always returns true. What I'd like to have happen, though, is for CanExecute to be tied to whether or not a file has been selected (i.e. to whether or not FilePath.Length > 0) and then link the button's status (enabled/disabled) to that. What's the best way to do this without adding an IsFileSelected observable property to Presenter?
Usually i have a base class for ICommand instances that takes a delegate for both its Execute and CanExecute methods. That being the case you can capture things in scope via closures. e.g. something along those lines:
private readonly DelegateCommand _executeCommand;
public DelegateCommand ExecuteCommand { /* get only */ }
public Presenter()
{
_excuteCommand = new DelegateCommand
(
() => /* execute code here */,
() => FilePath != null /* this is can-execute */
);
}
public string FilePath
{
get { return filePath; }
set
{
filePath = value;
RaisePropertyChangedEvent("FilePath");
ExecuteCommand.OnCanExecuteChanged(); // So the bound control updates
}
}

How to implement ICommand without parameters

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();
}
}

Categories

Resources