I have a search dialog where I want to disable the search button during the search. This is the current code but the button does not get deactivated
View:
You could try command can execute to disable the command without adding IsEnabled
property
private RelayCommand _startSearchCommand;
public RelayCommand StartSearchCommand
{
get
{
return _startSearchCommand??
(_startSearchCommand=
//Added can execute command , only execute if system is not busy at the moment.
new RelayCommand(async () => await OnExecuteSearch(), () => !IsBusy));
}
}
Command handler
internal async Task OnExecuteSearch()
{
IsBusy = true;
//Execute your action
//and finally
IsBusy = false;
}
Xaml
<Button Command="{Binding StartSearchCommand}">
The canexecute
in the Relay Command will control the IsEnabled
property for you.
I am not sure about looks when it was clicked and disabled - it is possible that it looks same.
But netaholic is right. If you execute logic in main UI thread it is possible that UI is frozen till your execution end (and isn't changed or changed to fast).
Try to put your logic in dispatcher. Like in next part of the code.
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => {
//do some searching here
}));
BTW, I took this code there.
EDIT: don't use this for your solution. This is wrong (check comments).
Use dispatcher when you need to update visual element async.
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => {
textbox.Content = "some result";
}));
I've made an AsyncDelegateCommand
for that reason (based on famous DelegateCommand), it internally disable command (in UI) during executing command action:
public class AsyncDelegateCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
bool _running;
public event EventHandler CanExecuteChanged;
public AsyncDelegateCommand(Action<object> execute, Predicate<object> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return (_canExecute == null ? true : _canExecute(parameter)) && !_running;
}
public async void Execute(object parameter)
{
_running = true;
Update();
await Task.Run(() => _execute(parameter));
_running = false;
Update();
}
public void Update()
{
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
}
xaml:
<Button Command="{Binding SomeCommand}" .../>
ViewModel:
AsyncDelegateCommand SomeCommand { get; }
// in constructor
SomeCommand = new AsyncDelegateCommand(o => { Thread.Sleep(5000); }); // code to run
This code must work.
private async void ExecuteSearch() {
IsNotSearching = false;
var task = Task.Factory.StartNew(() => {
//do some searching here
});
await task;
IsNotSearching = true;
}