Button command class to take a parameter - c#

Using c# + wpf + mvvm I am trying to make a more or less generic "buttoncommand" class following level 4 at http://www.codeproject.com/Articles/819294/WPF-MVVM-step-by-step-Basics-to-Advance-Level
I have a datagrid thats bound to observablecollection<mySpecialClass> and a button bound a command that adds row and takes no parameters that works fine.
However I would like to have buttons to insert and remove rows in the grid, that would take the index of the row that is currently active/selected.
I have tried to change the buttoncommand to the following (changing Action what to Action<object> what):
public class ButtonCommandi : ICommand
{
private Action<object> _whattoExecute;
private Func<bool> _whentoExecute;
public ButtonCommandi(Action<object> what, Func<bool> when)
{
_whattoExecute = what;
_whentoExecute = when;
}
public bool CanExecute(object parameter)
{
return _whentoExecute();
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_whattoExecute(parameter);
}
}
}
However, in my viewmodel, as I try to create instances of the class in the constructor:
public class MyViewModelClass
{
private ButtonCommand _objAppendTerrainPointCommand;
private ButtonCommandi _objInsertTerrainPointCommand;
private MyModelClass _mymodel;
public MyVeiwModelClass()
{
...
_objAppendRowCommand = new ButtonCommand(_mymodel.Append, _mymodel.IsPossibleToAppend);
_objInsertRowCommand= new ButtonCommandi(
delegate(object i) { _mymodel.InsertRow(i); }, _mymodel.IsPossibleToInsert);
...
}
it says that "the best overloaded method match for 'MyModelClass.InsertRow(int)' has some invalid arguments". I have tried some different versions of the new ButtonCommandi(..) but cannot seem to find the way.
in MyModelClass the function looks like this:
internal void InsertRow(int idx)
{
_myObsColSpecial.Insert(idx);
}
Does anyone have a good hint how to have this work? (I am new to the wpf, mvvm and c# so bear with me. As far as I understand there seems to be a lot of ways to accomplish something like this but since I started down this way, it would be nice not to have to rewrite a "ton" of code :) )

For RelayCommand that passes an object try this....
class RelayCommand<T> : ICommand
{
#region Fields
readonly Action<T> _execute = null;
readonly Predicate<T> _canExecute = null;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of <see cref="DelegateCommand{T}"/>.
/// </summary>
/// <param name="execute">Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.</param>
/// <remarks><seealso cref="CanExecute"/> will always return true.</remarks>
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
///<summary>
///Defines the method that determines whether the command can execute in its current state.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
///<returns>
///true if this command can be executed; otherwise, false.
///</returns>
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute((T)parameter);
}
///<summary>
///Occurs when changes occur that affect whether or not the command should execute.
///</summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
///<summary>
///Defines the method to be called when the command is invoked.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null" />.</param>
public void Execute(object parameter)
{
_execute((T)parameter);
}
#endregion
}
In your View Model...
class MainWindowVM
{
public RelayCommand<string> WindowCommand { get; set; }
public MainWindowVM()
{
WindowCommand = new RelayCommand<string>(OnWindowCommand);
}
private void OnWindowCommand(string obj)
{
// obj is the string passed from the Button CommandParameter
}
}
In your XAML
<Window.DataContext>
<local:MainWindowVM/>
</Window.DataContext>
<Grid>
<Button Command="{Binding WindowCommand}" CommandParameter="Test" />
</Grid>

Related

Pass class variable using CommandParameter in MVVM [duplicate]

This question already has an answer here:
Binding to properties in both the ViewModel and CodeBehind
(1 answer)
Closed 2 years ago.
I want to pass the ViewModel parameter(class variable) when I click the buttons in the View. When specifying a string, everything comes true, but I need to pass a non-string value from the View class(function AddNewField).
Main.xaml:
...
<Button
x:Name="ButtonAddingField"
CommandParameter="{Binding Path=Myprop}"
Command="{Binding Path=Myprop, RelativeSource={RelativeSource AncestorType=UserControl}}" />
...
Main.cs:
...
private Color myprop;
public Color Myprop
{
get => myprop;
}
...
this.DataContext = new FieldCollectionViewModel(fields); // fields - List<*my Model*>
...
FieldCollectionViewModel.cs:
...
private DelegateCommand<object> addFieldCommand;
public ICommand AddFieldCommand {
get {
if (addFieldCommand == null) addFieldCommand = new DelegateCommand<object>(AddNewField);
return addFieldCommand;
}
}
private void AddNewField(object parameter)
{
// !!! parameter = ALWAYS NULL
}
...
and my DelegateCommand.cs:
...
public class DelegateCommand<T> : ICommand
{
#region Constructors
/// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action<T> executeMethod)
: this(executeMethod, null, false)
{
}
/// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
: this(executeMethod, canExecuteMethod, false)
{
}
/// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
{
if (executeMethod == null) throw new ArgumentNullException("executeMethod");
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
_isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
}
#endregion Constructors
#region Public Methods
/// <summary>
/// Method to determine if the command can be executed
/// </summary>
public bool CanExecute(T parameter)
{
if (_canExecuteMethod != null) return _canExecuteMethod(parameter);
return true;
}
/// <summary>
/// Execution of the command
/// </summary>
public void Execute(T parameter)
{
if (_executeMethod != null) _executeMethod(parameter);
}
/// <summary>
/// Raises the CanExecuteChaged event
/// </summary>
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged();
}
/// <summary>
/// Protected virtual method to raise CanExecuteChanged event
/// </summary>
protected virtual void OnCanExecuteChanged()
{
CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
}
/// <summary>
/// Property to enable or disable CommandManager's automatic requery on this command
/// </summary>
public bool IsAutomaticRequeryDisabled {
get => _isAutomaticRequeryDisabled;
set {
if (_isAutomaticRequeryDisabled != value)
{
if (value)
CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
else
CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
_isAutomaticRequeryDisabled = value;
}
}
}
#endregion Public Methods
#region ICommand Members
/// <summary>
/// ICommand.CanExecuteChanged implementation
/// </summary>
public event EventHandler CanExecuteChanged {
add {
if (!_isAutomaticRequeryDisabled) CommandManager.RequerySuggested += value;
CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
}
remove {
if (!_isAutomaticRequeryDisabled) CommandManager.RequerySuggested -= value;
CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
}
}
bool ICommand.CanExecute(object parameter)
{
// if T is of value type and the parameter is not
// set yet, then return false if CanExecute delegate
// exists, else return true
if (parameter == null &&
typeof(T).IsValueType)
return _canExecuteMethod == null;
return CanExecute((T)parameter);
}
void ICommand.Execute(object parameter)
{
Execute((T)parameter);
}
#endregion ICommand Members
#region Data
private readonly Action<T> _executeMethod;
private readonly Func<T, bool> _canExecuteMethod;
private bool _isAutomaticRequeryDisabled;
private List<WeakReference> _canExecuteChangedHandlers;
#endregion Data
}
...
How can I solve my problem?
UPDATE.
I changed my code, now it is working
Thanks to #mm8
Myprop must be a public property of the DataContext of the Button for your current binding to work.
If it's a property of the parent UserControl, you could bind to it using a RelativeSource:
CommandParameter="{Binding Path=Myprop, RelativeSource={RelativeSource AncestorType=UserControl}}"
Note that you can only bind to public properties. You cannot bind to fields.

detect which button was clicked from ViewModel WPF

there are many buttons on the Main window of my WPF-App.
The commands of those buttons should have the same implementation/function but depending on which button has been pressed, the file/path on which the function accesses changes.
How to detect which button was clicked from ViewModel without using button click event handler (Windows forms)?
Here is the implementation of class RelayCommand:
public class RelayCommand : ICommand
{
readonly Func<Boolean> _canExecute;
readonly Action _execute;
public RelayCommand(Action execute)
: this(execute, null)
{
}
public RelayCommand(Action execute, Func<Boolean> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
CommandManager.RequerySuggested += value;
}
remove
{
if (_canExecute != null)
CommandManager.RequerySuggested -= value;
}
}
public Boolean CanExecute(Object parameter)
{
return _canExecute == null ? true : _canExecute();
}
public void Execute(Object parameter)
{
_execute();
}
}
Here is the code of the command in ViewModel:
void DoThisWorkExecute()
{
// if Button1 is clicked...do this
// if Button2 is clicked...do this
}
bool CanDoThisWorkExecute()
{
return true;
}
public ICommand ButtonCommand { get { return new RelayCommand(DoThisWorkExecute, CanDoThisWorkExecute); } }
You can use the CommandParameter. Something like that:
<Button Content="Open" Command="{Binding Path=ButtonCommand}" CommandParameter="Open"/>
<Button Content="Save" Command="{Binding Path=ButtonCommand}" CommandParameter="Save"/>
For this you need a slightly different implementation of the RelayCommand
/// <summary>
/// https://gist.github.com/schuster-rainer/2648922
/// Implementation from Josh Smith of the RelayCommand
/// </summary>
public class RelayCommand : ICommand
{
#region Fields
readonly Predicate<object> _canExecute;
readonly Action<object> _execute;
#endregion // Fields
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="RelayCommand"/> class.
/// </summary>
/// <param name="execute">The execute.</param>
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RelayCommand"/> class.
/// </summary>
/// <param name="execute">The execute.</param>
/// <param name="canExecute">The can execute.</param>
/// <exception cref="System.ArgumentNullException">execute</exception>
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
/// <summary>
/// Occurs when changes occur that affect whether or not the command should execute.
/// </summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
/// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
/// <returns>true if this command can be executed; otherwise, false.</returns>
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
/// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
However: Instead of asking which button was clicked, I would make a Command for each separate action (e.g. open, save, exit). You will have much less troubles when reusing your commands (context menu, KeyBindings, toolbar, etc.). You would always have to provide the ui element. This really breaks the MVVM pattern. You really have to get rid of the old winforms approach, in order to use the full power of the RelayCommand.
I wrote myself a code snippet so I don't have to write all the code.
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>RelayCommand</Title>
<Shortcut>RelayCommand</Shortcut>
<Description>Code snippet for usage of the Relay Command pattern</Description>
<Author>Mat</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>name</ID>
<ToolTip>Name of the command</ToolTip>
<Default>Save</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[ private RelayCommand _$name$Command;
public ICommand $name$Command
{
get
{
if (_$name$Command == null)
{
_$name$Command = new RelayCommand(param => this.$name$(param),
param => this.Can$name$(param));
}
return _$name$Command;
}
}
private bool Can$name$(object param)
{
return true;
}
private void $name$(object param)
{
MessageServiceHelper.RegisterMessage(new NotImplementedException());
}]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
see also https://msdn.microsoft.com/en-us/library/z41h7fat.aspx

Universal Windows WPF CommandParameter bind to static Enumeration

I need help on 2 things.
sending parameters (which is a static Enum) from a view to the viewmodel (I know I must use the CommandParameter on my button).
How to delcare my DelegateCommand class so that it can accept the parameter.
Enumeration :
public static class Helpers
{
public enum Operations
{
ONE,
TWO
}
}
ViewModel
public class SettingViewModel : ViewModelBase
{
private DelegateCommand _UpdateCommand;
public ICommand UpdateOperationValue
{
get
{
if (_UpdateCommand== null)
_UpdateCommand= new DelegateCommand(Of Helpers.Operations)(param => UpdatePaint()); // Gives me erreur
return _UpdateCommand;
}
}
}
View:
<Button Height="100" Width="100" Content="PEINTURE"
Background="{Binding PaintColorBrush}"
Command="{Binding UpdateOperationValue}"
CommandParameter="[... What do I do here ? ...]"/>
I've been searching on the web for solutions and came accross this :
<Button CommandParameter="{x:Static local:SearchPageType.First}" .../>
sadly in Universal Windows app I don't have the x:Static
My DelegateCommand class :
using System;
using System.Windows.Input;
public class DelegateCommand : ICommand
{
/// <summary>
/// Action to be performed when this command is executed
/// </summary>
private Action<object> _executionAction;
/// <summary>
/// Predicate to determine if the command is valid for execution
/// </summary>
private Predicate<object> _canExecutePredicate;
/// <summary>
/// CanExecuteChanged event handler
/// </summary>
public event EventHandler CanExecuteChanged;
/// <summary>
/// Initialize a new instance of the clDelegateCommand class
/// The command will always be valid for execution
/// </summary>
/// <param name="execute">The delegate to call on execution</param>
public DelegateCommand(Action<object> execute)
: this(execute, null)
{ }
/// <summary>
/// Initializes a new instance of the clDelegateCommand class
/// </summary>
/// <param name="execute">The delegate to call on execution</param>
/// <param name="canExecute">The predicate to determine if the command is valid for execution</param>
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
this._executionAction = execute;
this._canExecutePredicate = canExecute;
}
/// <summary>
/// Raised when CanExecute is changed
/// </summary>
public void RaiseCanExecuteChanged()
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
/// <summary>
/// Execute the delegate backing this DelegateCommand
/// </summary>
/// <param name="parameter"></param>
/// <returns>True if command is valid for execution</returns>
public bool CanExecute(object parameter)
{
return this._canExecutePredicate == null ? true : this._canExecutePredicate(parameter);
}
/// <summary>
/// Execute the delegate backing this DelegateCommand
/// </summary>
/// <param name="parameter">parameter to pass to delegate</param>
/// <exception cref="InvalidOperationException">Thrown if CanExecute returns false</exception>
public void Execute(object parameter)
{
if (!CanExecute(parameter))
{
throw new InvalidOperationException("The command is not valid for execution, check the CanExecute method before attempting to execute.");
}
this._executionAction(parameter);
}
}
How can I send a enum parameter from my view to my view model
How can I instanciate a new DelegateCommand and receiving a enum as parameters.
How to delcare my DelegateCommand class so that it can accept the parameter.
You can use below class to accept parameters,
public class DelegateCommand: ICommand
{
#region Constructors
public DelegateCommand(Action<object> execute)
: this(execute, null) { }
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return _canExecute != null ? _canExecute(parameter) : true;
}
public void Execute(object parameter)
{
if (_execute != null)
_execute(parameter);
}
public void OnCanExecuteChanged()
{
CanExecuteChanged(this, EventArgs.Empty);
}
#endregion
private readonly Action<object> _execute = null;
private readonly Predicate<object> _canExecute = null;
}
In ViewModel ICommand Property example below,
public ICommand ExitCommand
{
get
{
if (exitCommand == null)
{
exitCommand = new DelegateCommand((obj)=>CloseApplication());
}
return exitCommand;
}
}
How can I send a enum parameter from my view to my view model
Commandparameter accept object. Bind your enum to CommandParameter and cast it in your ViewModel

Button command binding doesn't work

I created a new UserContol with a button inside. Iwanted to bind the button command to a dependancy property of the new user control like this.
<Grid>
<Button Name="Button1" Command="{Binding Button1Command}" />
</Grid>
this is the DP on the containing UserControl:
public ICommand Button1Command
{
get { return (ICommand)GetValue(Button1CommandProperty); }
set { SetValue(Button1CommandProperty, value); }
}
public static readonly DependencyProperty Button1CommandProperty =
DependencyProperty.Register("Button1Command", typeof(ICommand), typeof(BptCellTemplate), new FrameworkPropertyMetadata(null));
when i try to use it nothing happen when I press the button. It doesn't recognize the command. If I add an event it works. Like this:
public static readonly DependencyProperty Button1CommandProperty =
DependencyProperty.Register("Button1Command", typeof(ICommand), typeof(BptCellTemplate), new FrameworkPropertyMetadata(null, OnButton1CommandChanged));
private static void OnButton1CommandChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs args)
{
var bptCellTemplate = dependencyObject as BptCellTemplate;
if (bptCellTemplate == null || !(args.NewValue is ICommand))
{
return;
}
(bptCellTemplate.DataContext as BptCellTemplateViewModel).Button1Command = (ICommand)args.NewValue;
}
Is there a way to bind it without an event? because it works with other button properties that i did the same way (Visibility for example)
It's possible that your binding is not working because there is nothing that says the Button1Command property is a member of your UserControl.
You can confirm that this is the problem by looking in the Output window when debugging your program in Visual Studio. You'll likely see binding errors that member Button1Command wasn't found.
The typical fix for this is to add a name attribute to your UserControl's root element, such as x:Name="root" (you can choose your own name or use an existing one if you have it). Then, change your binding to the command to reference the new name:
<Button Name="Button1" Command="{Binding Button1Command, ElementName=root}" />
You need class implements ICommand interface.
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
/// <summary>
/// Creates a new command that can always execute.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
Now there is binding very simple.
Define Command in your DataContext (MVVM ...ect.)
Don't remember setup DataContext ... for example DataContext = this; (this is your Window)
RelayCommand _btnCommand;
public ICommand Button1Command
{
get
{
if (_btnCommand == null)
{
_btnCommand = new RelayCommand(param => this.ExecuteButton1(),
param => this.CanButton1());
}
return _btnCommand;
}
}
public void ExecuteButton1()
{
}
public bool CanButton1()
{
return true;
}
That's it ...

Re-evaluating CanExecute on property change

I am trying to implement ICommandSource on a custom control (similar to a button). Currently the implementation is mostly like it is displayed on the msdn page for ICommandSource and as it shows in the ButtonBase source code.
CanExecute fires on load of the control but doesn't fire when any property has changed. The same command being passed to a regular button works just fine. When the property that is supposed to change changes, CanExecute fires and the button is enabled. The command is a Delegate Command.
I have tried CommandManager.InvalidateRequerySuggested(); but that has not worked.
Any ideas?
Here's the implementation in the custom control:
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CollapsibleSplitButton csb = (CollapsibleSplitButton)d;
csb.OnCommandChanged((ICommand)e.OldValue, (ICommand)e.NewValue);
}
private void OnCommandChanged(ICommand oldCommand, ICommand newCommand)
{
if (oldCommand != null) UnhookCommand(oldCommand);
if (newCommand != null) HookCommand(newCommand);
}
private void UnhookCommand(ICommand command)
{
command.CanExecuteChanged -= OnCanExecuteChanged;
UpdateCanExecute();
}
private void HookCommand(ICommand command)
{
command.CanExecuteChanged += OnCanExecuteChanged;
UpdateCanExecute();
}
private void OnCanExecuteChanged(object sender, EventArgs e)
{
UpdateCanExecute();
}
private void UpdateCanExecute()
{
if (Command != null)
CanExecute = Command.CanExecute(CommandParameter);
else
CanExecute = true;
}
protected override bool IsEnabledCore
{
get { return base.IsEnabledCore && CanExecute; }
}
Where I setup the Command I have:
...
MyCommand = new DelegatingCommand(DoStuff, CanDoStuff);
...
private bool CanDoStuff()
{
return (DueDate == null);
}
private void DoStuff() {//do stuff}
With delegate commands, you have to raise the CanExecuteChanged explicitly whenever you think it should be updated on UI. Try using this version of command called RelayCommand -
public class RelayCommand<T> : ICommand
{
#region Fields
readonly Action<T> _execute = null;
readonly Predicate<T> _canExecute = null;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of <see cref="DelegateCommand{T}"/>.
/// </summary>
/// <param name="execute">Delegate to execute when Execute is called on the command.
///This can be null to just hook up a CanExecute delegate.</param>
/// <remarks><seealso cref="CanExecute"/> will always return true.</remarks>
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
///<summary>
///Defines the method that determines whether the command can execute in its current
///state.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require
/// data to be passed, this object can be set to null.</param>
///<returns>
///true if this command can be executed; otherwise, false.
///</returns>
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute((T)parameter);
}
///<summary>
///Occurs when changes occur that affect whether or not the command should execute.
///</summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
///<summary>
///Defines the method to be called when the command is invoked.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require
///data to be passed, this object can be set to <see langword="null" />.</param>
public void Execute(object parameter)
{
_execute((T)parameter);
}
#endregion
}
And register like Delegate commands in your class-
public ICommand TestCommand { get; private set; }
TestCommand = new RelayCommand<object>(CommandMethod, CanExecuteCommand);
EDIT
Try putting CommandManager.InvalidateRequerySuggested(); in your CanExecute -
private void OnCanExecuteChanged(object sender, EventArgs e)
{
CommandManager.InvalidateRequerySuggested();
UpdateCanExecute();
}
Managed to resolve the issue by wrapping the callback in an EventHandler.
private EventHandler currentHandler;
private void UnhookCommand(ICommand command)
{
if (currentHandler != null)
command.CanExecuteChanged -= currentHandler;
UpdateCanExecute();
}
private void HookCommand(ICommand command)
{
if (currentHandler == null) return;
command.CanExecuteChanged += currentHandler;
UpdateCanExecute();
}

Categories