Pass class variable using CommandParameter in MVVM [duplicate] - c#

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.

Related

Is this call really async?

Following:
Converting Action method call to async Action method call
and
The 'await' operator can only be used within an async lambda expression
I've come up with the following code:
CommandHandler.cs:
public class CommandHandler : ICommand
{
private Func<Task> _action;
private Func<bool> _canExecute;
/// <summary>
/// Creates instance of the command handler
/// </summary>
/// <param name="action">Action to be executed by the command</param>
/// <param name="canExecute">A bolean property to containing current permissions to execute the command</param>
public CommandHandler(Func<Task> action, Func<bool> canExecute)
{
_action = action;
_canExecute = canExecute;
}
/// <summary>
/// Wires CanExecuteChanged event
/// </summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
/// <summary>
/// Forcess checking if execute is allowed
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
public bool CanExecute(object parameter)
{
return _canExecute.Invoke();
}
public void Execute(object parameter)
{
_action(); // IS THIS REALLY ASYNC? VS DOESN'T COMPLAIN
}
}
AppliedJobsViewModel.cs:
class AppliedJobsViewModel
{
private TexParser texParser;
private ObservableCollection<AppliedJob> appliedJobsCollection;
public AppliedJobsViewModel() {
// TODO:
// -- do nothing here
}
public ObservableCollection<AppliedJob> AppliedJobsCollection
{
get
{
if (appliedJobsCollection == null)
{
appliedJobsCollection = new ObservableCollection<AppliedJob>();
}
return appliedJobsCollection;
}
set
{
if (value != null)
{
appliedJobsCollection = value;
}
}
}
private ICommand _openTexClick;
public ICommand OpenTexClick
{
get
{
return _openTexClick ?? (_openTexClick = new CommandHandler(() => ReadAndParseTexFile(), () => CanExecute));
}
}
public bool CanExecute
{
get
{
// check if executing is allowed, i.e., validate, check if a process is running, etc.
return true;
}
}
public async Task ReadAndParseTexFile()
{
if (texParser == null)
{
texParser = new TexParser();
}
// Read file asynchronously here
await Task.Run(() => ReadFileAndUpdateUI()); // LARGE SYNC CHUNK OF CODE
}
private void ReadFileAndUpdateUI()
{
texParser.ReadTexFile();
string[][] appliedJobsArray = texParser.getCleanTable();
// Update collection here
List<AppliedJob> appliedJobsList = createAppliedJobsListFromTable(appliedJobsArray);
appliedJobsCollection = new ObservableCollection<AppliedJob>(appliedJobsList);
}
private List<AppliedJob> createAppliedJobsListFromTable(string[][] table)
{
List<AppliedJob> jobsList = new List<AppliedJob>();
for (int i = 0; i < table.Length; i++)
{
jobsList.Add(new AppliedJob(table[i]));
}
return jobsList;
}
public ObservableCollection<AppliedJob> AppliedJobs {
get;
set;
}
}
Is the code "entirely"(from the start of the Func action) async? If yes, is it "fully" MVVM? If not, why?

Set up button's IsEnabled property with ICommand [duplicate]

This question already has answers here:
WPF MVVM command canexecute enable/disable button
(4 answers)
Disable button in WPF?
(5 answers)
How does one "disable" a button in WPF using the MVVM pattern?
(5 answers)
Command source disabling and enabling
(1 answer)
Closed 5 years ago.
I have the command
public class RelayActionCommand : ICommand
{
/// <summary>
/// The Action Delegate representing a method with input parameter
/// </summary>
public Action<object> ExecuteAction { get; set; }
/// <summary>
/// The Delegate, used to represent the method which defines criteria for the execution
/// </summary>
public Predicate<object> CanExecuteAction { get; set; }
public bool CanExecute(object parameter)
{
if (CanExecuteAction != null)
{
return CanExecuteAction(parameter);
}
return true;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
if (ExecuteAction != null)
{
ExecuteAction(parameter);
}
}
}
To use it,
public RelayActionCommand SearchPersonCommnad { get; set; }
DataAccess objds;
public PersonViewModel()
{
Persons = new ObservableCollection<PersonInfo>();
objds = new DataAccess();
Persons = new ObservableCollection<PersonInfo>(objds.GetPersonData());
var defaultView = CollectionViewSource.GetDefaultView(Persons);
//based upon the data entered in the TextBox
SearchPersonCommnad = new RelayActionCommand()
{
CanExecuteAction = n=> !String.IsNullOrEmpty(Name),
ExecuteAction = n => defaultView.Filter = name => ((PersonInfo)name).FirstName.StartsWith(Name)
|| ((PersonInfo)name).LastName.StartsWith(Name)
|| ((PersonInfo)name).City==Name
};
At the beginning, the button is disabled. But in running time, it changes by different situations. My question is how to set up the button's IsEnabled property with it? Which means, when ExecuteAction I have to set up the property correctly.
UPDATE:
I use ICommand not DelegateCommand.
You can use the CanExecute method, but it is good practice is actually to avoid this, and bind the button's enabled state to a separate boolean property of the view model. Most other solutions will have unexpected effects, or be suboptimal. Why?
CanExecute is a method. This means that it needs to be polled for the button state to change. You can force the control that's using the command to re-poll on a status change, but the code is much cleaner and more straightforward if you just use a property on the view model. This is because as a method, you can't use INotifyPropertyChanged to notify for changes, whereas with a property you can.
The danger in using CanExecute is that the user will manage to click the button after the method would return false, but before the button's enablement has changed.
Edit: Code to do what you want:
public class ViewModel : INotifyPropertyChanged
{
private int someValue;
private bool isEnabled;
public ViewModel()
{
MyCommand = new RelayActionCommand(Click);
}
private void Click(object obj)
{
//Do something.
}
/// <summary>
/// Bind this to the IsEnabled property of the button, and
/// also the background using a convertor or see ButtonBackground.
/// </summary>
public bool IsEnabled => SomeValue < 5;
/// <summary>
/// Option 2 - use this property to bind to the background of the button.
/// </summary>
public Brush ButtonBackground => IsEnabled ? Brushes.SeaShell : Brushes.AntiqueWhite;
public int SomeValue
{
get { return someValue; }
set
{
if (value == someValue) return;
someValue = value;
OnPropertyChanged();
OnPropertyChanged(nameof(IsEnabled));
OnPropertyChanged(nameof(ButtonBackground));
}
}
/// <summary>
/// Bind this to the command of the button.
/// </summary>
public RelayActionCommand MyCommand { get; }
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged
([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Relay command fixed up a bit to avoid using CanExecute:
public class RelayActionCommand : ICommand
{
public RelayActionCommand(Action<object> executeAction)
{
ExecuteAction = executeAction;
}
/// <summary>
/// The Action Delegate representing a method with input parameter
/// </summary>
public Action<object> ExecuteAction { get; }
/// <summary>
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
ExecuteAction?.Invoke(parameter);
}
//Deliberately empty.
public event EventHandler CanExecuteChanged
{
add { }
remove { }
}
}
EDIT 2: Code to do what you want using a DelegateCommand
Note, this does not use InvalidateRequerySuggested - mainly because it refreshes all buttons when any CanExecute changes, which is a poor solution. As you can see, this is less immediately straightforward than putting the code in the view model directly, but whatever floats your boat I guess.
public sealed class ViewModel : INotifyPropertyChanged
{
private int calls;
public ViewModel()
{
SafeOnceCommand = new RelayCommand(DoItOnce, HasDoneIt);
}
private bool HasDoneIt()
{
return Calls == 0;
}
private void DoItOnce()
{
if (Calls > 0) throw new InvalidOperationException();
Calls++;
}
public int Calls
{
get { return calls; }
set
{
if (value == calls) return;
calls = value;
OnPropertyChanged();
SafeOnceCommand.RaiseCanExecuteChanged();
}
}
public RelayCommand SafeOnceCommand { get; }
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public sealed class RelayCommand : ICommand
{
private readonly Action execute;
private readonly Func<bool> canExecute;
private readonly List<EventHandler> invocationList = new List<EventHandler>();
public RelayCommand(Action execute, Func<bool> canExecute)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute();
}
public void Execute(object parameter)
{
execute();
}
/// <summary>
/// Method to raise CanExecuteChanged event
/// </summary>
public void RaiseCanExecuteChanged()
{
foreach (var elem in invocationList)
{
elem(null, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged
{
add { invocationList.Add(value); }
remove { invocationList.Remove(value); }
}
}

Button command class to take a parameter

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>

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

CanExecute of command doesn't work in listbox

I've a listbox that contains some "Application" objects. An "Application" object can be started or stopped.
For each element in my Listbox I've 2 buttons, the first to start application and the second to stop the application.
But, when I click on Start button, the CanExecute of command "Stop" isn't reevaluated until I click inside the application, despite the "CommandManager.InvalidateRequerySuggested();"
<ListBox Grid.Row="1" ItemsSource="{Binding Applications}" Grid.ColumnSpan="3" BorderThickness="0" Background="#FFE8E8E8" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Margin="5,0" Content = "Start"
Command="{Binding StartCommand}"
Visibility="{Binding IsRunning, Converter={Converters:InvertedBoolToVisibilityConverter}}"/>
<Button Margin="5,0" Content = "Stop"
Command="{Binding StopCommand}"
Visibility="{Binding IsRunning, Converter={Converters:BoolToVisibilityConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
On ApplicationViewModel :
public bool IsRunning
{
get
{
return this.m_IsRunning;
}
set
{
this.m_IsRunning = value;
this.OnPropertyChanged("IsRunning");
CommandManager.InvalidateRequerySuggested();
}
}
public ICommand StartCommand
{
get
{
if (this.m_StartCommand == null)
{
this.m_StartCommand = new RelayCommand(p => !this.IsRunning, p => this.Start());
}
return this.m_StartCommand;
}
}
public ICommand StopCommand
{
get
{
if (this.m_StopCommand == null)
{
this.m_StopCommand = new RelayCommand(p => this.IsRunning, p => this.Stop());
}
return this.m_StopCommand;
}
}
My RelayCommand Class :
public class RelayCommand : ICommand
{
#region Member Fields
/// <summary>
/// Contains the list of actions.
/// </summary>
private readonly Action<object> _execute;
/// <summary>
/// Contains the predicate _canExecute.
/// </summary>
private readonly Predicate<object> _canExecute;
#endregion
#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(null, execute)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RelayCommand"/> class.
/// </summary>
/// <param name="canExecute">The can execute.</param>
/// <param name="execute">The execute.</param>
public RelayCommand(Predicate<object> canExecute, Action<object> execute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
this._execute = execute;
this._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>
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return this._canExecute == null ? true : this._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)
{
this._execute(parameter);
}
#endregion
}
Try RaiseCanExecuteChanged() of your StopCommand directly in your handler of StartCommand.
If you have implemented the your Command yourself, then you can add RaiseCanExecuteChanged to it like. It will call CanExecuteChanged event
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}

Categories