mvvmlight
mvvmlight copied to clipboard
Could anyone suggest a neat way to Dis-/Enable buttons
Hello everyone, could anyone suggest a neat way to dis-/enable buttons? Currently I'm doing such things as follows:
ViewModel:
// Properties
public bool Save_btn_is_enabled
{
get { return _save_btn_is_enabled; }
set { Set(ref _save_btn_is_enabled, value); }
}
private bool _save_btn_is_enabled;
// Constructor
Window_ViewModel()
{
DoSomething_command = new RelayCommand(DoSomethingMethod);
Save_btn_is_enabled = true;
}
// do something method
privat async void DoSomethingMethod()
{
Save_btn_is_enabled = false;
// do smth here before dealying
await Task.Delay(clickActionDelay1)
// do smth here after delaying
Save_btn_is_enabled = true;
}
ICommand and RelayCommand have a Func<bool> canExecute as well as an Action execute. When a button binds to an ICommand the enabled state binds to CanExecute and is updated on the CanExecuteChanged event. See the MVVM light sample RaiseCanExecuteChanged Sample
IMHO, this is quite bad example on how this works. Also I couldn't open this sample with VS2015. Perhaps does anyone have better ones?
@DeputyOfCopyPaster from your example it looks like you are trying to disable access while an async action is in process. If that is the case what you are doing is perfectly fine. Here is an example using ICommand that does not allow concurrent execution. Example
XAML
<Button
Text="Give me coffee !"
Command="{Binding Submit}" />
CODE
public interface IAsyncCommand : ICommand
{
Task ExecuteAsync();
bool CanExecute();
}
public class AsyncCommand : IAsyncCommand
{
public event EventHandler CanExecuteChanged;
private bool _isExecuting;
private readonly Func<Task> _execute;
private readonly Func<bool> _canExecute;
private readonly IErrorHandler _errorHandler;
public AsyncCommand(
Func<Task> execute,
Func<bool> canExecute = null,
IErrorHandler errorHandler = null)
{
_execute = execute;
_canExecute = canExecute;
_errorHandler = errorHandler;
}
public bool CanExecute()
{
return !_isExecuting && (_canExecute?.Invoke() ?? true);
}
public async Task ExecuteAsync()
{
if (CanExecute())
{
try
{
_isExecuting = true;
await _execute();
}
finally
{
_isExecuting = false;
}
}
RaiseCanExecuteChanged();
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
#region Explicit implementations
bool ICommand.CanExecute(object parameter)
{
return CanExecute();
}
void ICommand.Execute(object parameter)
{
ExecuteAsync().FireAndForgetSafeAsync(_errorHandler);
}
#endregion
}
public class MainViewModel : ViewModelBase
{
private bool _isBusy;
public bool IsBusy
{
get => _isBusy;
private set => Set(ref _isBusy, value);
}
public IAsyncCommand Submit { get; private set; }
public MainViewModel()
{
Submit = new AsyncCommand(ExecuteSubmitAsync, CanExecuteSubmit);
}
private async Task ExecuteSubmitAsync()
{
try
{
IsBusy = true;
var coffeeService = new CoffeeService();
await coffeeService.PrepareCoffeeAsync();
}
finally
{
IsBusy = false;
}
}
private bool CanExecuteSubmit()
{
return !IsBusy;
}
}