(я впервые пытаюсь использовать CanExecute для ICommand, поэтому будьте терпеливы)
Кнопка привязана к команде в модели представления.
При нажатии кнопки запускается длительный процесс (я вызываю его с помощью await Task.Run(), чтобы пользовательский интерфейс не блокировался).
(Затем я обновляю ObservableCollection в ViewModel для отображения результатов в пользовательском интерфейсе, но я не включаю эту часть здесь для простоты)
Теперь я хочу отключить кнопку при ее нажатии и включить ее после завершения длительного процесса. Я объявил частное поле и свойство в модели представления IsBusy, а в методе, связанном с CanExecute команды, я возвращаю true или false в зависимости от значения этого свойства.
Это половина работы: при нажатии кнопки она отключается. Затем, когда процесс завершается, пользовательский интерфейс показывает результаты в порядке, НО кнопка не включается повторно... только когда я после этого нажимаю где-нибудь в пользовательском интерфейсе, кнопка снова включается...
в xaml:
Код: Выделить всё
Код: Выделить всё
public class MyViewModel : BaseViewModel {
public ICommand DoProcessCommand { get; private set; }
private bool _isBusy;
public bool IsBusy {
get { return _isBusy; }
set { _isBusy = value; OnPropertyChanged(nameof(IsBusy)); }
}
//ctor
public MyViewModel() {
DoProcessCommand = new RelayCommand(DoProcessCommandMethod, CanDoProcessCommandMethod);
IsBusy = false;
}
//Command Execute
private bool CanDoProcessCommandMethod(object parameter) {
return !IsBusy;
}
//Command CanExecute
private async void DoProcessCommandMethod(object parameter) {
IsBusy = true;
var results = await Task.Run(() => MyService.someLongProcess());
// so something with the results...
IsBusy = false;
// more code here...
}
}
обратите внимание: метод, выполняющий длинный процесс, не является асинхронным, я просто вызываю его внутри await Task.Run(), чтобы он не блокировал поток пользовательского интерфейса... Я просто упоминаю об этом на случай, если это на что-то повлияет...
ОБНОВЛЕНИЕ
Я забыл добавить свою реализацию RelayCommand, просто в случай...
RelayCommand.cs
Код: Выделить всё
public class RelayCommand : ICommand {
readonly Action _execute = null;
readonly Predicate _canExecute = null;
public RelayCommand(Action execute)
: this(execute, null) {
}
public RelayCommand(Action execute, Predicate canExecute) {
if (execute == null) throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) {
return _canExecute == null ? true : _canExecute((T)parameter);
}
public event EventHandler CanExecuteChanged {
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter) {
_execute((T)parameter);
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... h-task-run
Мобильная версия