Reputation: 2923
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
?
Upvotes: 1
Views: 669
Reputation: 185445
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
}
}
Upvotes: 3