Reputation: 31
All I want to do is pass a parameter from xaml into a viewmodel. The CanExecuteChanged event is not firing for my command in order to enable a button which performs an operation.
I have no problem executing this logic if no parameter is passed into the viewmodel.
I think something needs to be changed in my Relaycommand class. Can somebody please help me configure this properly? I have viewed the answers to this type of question, but still am having trouble getting the Delete button enabled in order to execute the DeleteThanks method.
In the ICommand.CanExecute method of the RelayCommand class, the _TargetCanExecuteMethod & _TargetExecuteMethod are always null; therefore, not executing the CanDeleteThanks method in the viewmodel.
Note that the second RelayCommand method in the same named class needed to be inserted there due to the signature of the Delete command. However, those objects inside that method are not implemented in the ICommand.CanExecute method.
Here is my xaml:
<Button x:Name="btnDelete"
Content="Delete"
Command="{Binding DeleteThanksCommand}"
CommandParameter="{Binding Text, ElementName=Subject}"
IsEnabled="{Binding DeleteEnabled}"
HorizontalAlignment="Left"
Grid.Row="0"
Grid.Column="0" Foreground="#FF0C1334">
</Button>
Here is my viewmodel:
public GiveThanksViewModel()
{
DeleteThanksCommand = new RelayCommand(param => DeleteThanks(param), param => CanDeleteThanks(param));
}
private bool _DeleteEnabled;
public bool DeleteEnabled
{
get
{
return _DeleteEnabled;
}
set
{
if (_DeleteEnabled != value)
{
_DeleteEnabled = value;
}
}
}
public RelayCommand DeleteThanksCommand { get; private set; }
private void DeleteThanks(object action)
{
try
{
...
DeleteEnabled = false;
DeleteThanksCommand.RaiseCanExecuteChanged();
}
}
catch (Exception ex)
{
messageService.ShowNotification(ex.Message);
}
}
private bool CanDeleteThanks(object parameter)
{
return DeleteEnabled;
}
Here is the Relaycommand class:
public class RelayCommand : ICommand
{
Action _TargetExecuteMethod;
Func<bool> _TargetCanExecuteMethod;
private Action<object> action;
private Func<object, bool> canDeleteThanks;
public RelayCommand(Action executeMethod, Func<bool> canExecuteMethod)
{
_TargetExecuteMethod = executeMethod;
_TargetCanExecuteMethod = canExecuteMethod;
}
public RelayCommand(Action<object> action, Func<object, bool> canDeleteThanks)
{
this.action = action;
this.canDeleteThanks = canDeleteThanks;
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged(this, EventArgs.Empty);
}
#region ICommand Members
bool ICommand.CanExecute(object parameter)
{
if (_TargetCanExecuteMethod != null)
{
return _TargetCanExecuteMethod();
}
if (_TargetExecuteMethod != null)
{
return true;
}
return false;
}
// Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
// Prism commands solve this in their implementation
public event EventHandler CanExecuteChanged = delegate { };
void ICommand.Execute(object parameter)
{
if (_TargetExecuteMethod != null)
{
_TargetExecuteMethod();
}
}
#endregion
}
Here is the other half of the code in the same RelayCommand class which never gets executed when debugging. I think that the below code needs to get executed because of my parameter.
public class RelayCommand<T> : ICommand
{
Action<T> _TargetExecuteMethod;
Func<T, bool> _TargetCanExecuteMethod;
public RelayCommand(Action<T> executeMethod, Func<T,bool> canExecuteMethod)
{
_TargetExecuteMethod = executeMethod;
_TargetCanExecuteMethod = canExecuteMethod;
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged(this, EventArgs.Empty);
}
#region ICommand Members
bool ICommand.CanExecute(object parameter)
{
if (_TargetCanExecuteMethod != null)
{
T tparm = (T)parameter;
return _TargetCanExecuteMethod(tparm);
}
if (_TargetExecuteMethod != null)
{
return true;
}
return false;
}
// Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
// Prism commands solve this in their implementation
public event EventHandler CanExecuteChanged = delegate { };
void ICommand.Execute(object parameter)
{
if (_TargetExecuteMethod != null)
{
_TargetExecuteMethod((T)parameter);
}
}
#endregion
}
Upvotes: 1
Views: 5867
Reputation: 31
I got it to work by modifying the following:
In the ViewModel, I changed to the following from my original code:
DeleteThanksCommand = new RelayCommand<object>((parms) => DeleteThanks(parms), parms => CanDeleteThanks());
public RelayCommand<object> DeleteThanksCommand { get; private set; }
Upvotes: 2