Странная проблема, когда Button не включается, если не щелкнуть мышью - PullRequest
23 голосов
/ 25 февраля 2010

Мое приложение написано с использованием шаблона MVVM в WPF, и все мои кнопки используют привязки команд для выполнения кода в моей модели. Все команды имеют код в CanExecute для определения состояния «Включено» связанной кнопки. Логика работает отлично, но во всех случаях GUI остается в отключенном состоянии, если я не щелкну где-нибудь еще в GUI.

Например, у меня есть кнопка Discard Candy. Когда я нажимаю эту кнопку, он запускает процесс в потоке потоков, который устанавливает для свойства bool с именем Running значение true . Так как метод CanExecute для команды Discard Candy выглядит примерно так

public bool CanExecute(object parameter)
{
  return !Running;
}

кнопка будет отключена после запуска процесса. Проблема заключается в том, что когда процесс завершен, для параметра Running установлено значение false , но графический интерфейс не обновляется, т. Е. Discard Candy не включается повторно.

Однако, если я нажимаю в любом месте графического интерфейса, например в окне или строке заголовка, кнопка Discard Candy внезапно становится активной. Так что логика работает, но происходит что-то, чего я просто не понимаю. Может кто-нибудь объяснить мне это поведение?

РЕДАКТИРОВАТЬ - до сих пор это звучит как CommandManager. InvalidateRequerySuggested не помог людям. Я собираюсь дать ему шанс, но на данный момент я немного осторожен с этим. Я перешел по рекомендованным ссылкам и решил прочитать больше о легком инструментарии MVVM. Звучит очень хорошо - кто-нибудь здесь использовал это и смог подтвердить, что это не показывает проблему, с которой я сталкивался до сих пор? Хотя я планирую попробовать легкий инструментарий MVVM в следующем крупном выпуске. моего приложения я не хочу возвращать все команды, которые у меня есть на данный момент, поэтому, скорее всего, я начну с CommandManager.InvalidateRequerySuggested, чтобы мы могли получить еще одну точку данных относительно ее полезности.

EDIT # 2 - очень интересно, легкий инструментарий MVVM на самом деле полагается на CommandManager.InvalidateRequerySuggested для поддержки способности пользовательского интерфейса отключать / повторно включать команды. Автор говорит:

"Строго говоря, в WPF, и если ваша команда связана с элементом управления, который отслеживается CommandManager, вам не нужно вызывать событие CanExecuteChanged самостоятельно. Вы можете позволить CommandManager справиться с ситуацией. внешние события также могут изменить состояние пользовательского интерфейса. Давайте представим, что пользовательский интерфейс должен быть включен с 9:00 до 17:00, а затем отключен на ночь. Пользователь не запускает пользовательский интерфейс, поэтому код должен (вежливо) запросить CommandManager запрашивает состояние команд. Это делается путем вызова метода InvalidateRequerySuggested в CommandManager. И, как вы уже догадались, метод RaiseCanExecuteChanged класса RelayCommand делает именно это."

Ответы [ 3 ]

20 голосов
/ 25 февраля 2010

WPF не обновляет привязанные к команде элементы управления, если для этого нет причины. При щелчке по графическому интерфейсу WPF обновляется, поэтому обновление работает.

Вы можете вручную вызвать обновление любых связанных с командой элементов управления, вызвав CommandManager.InvalidateRequerySuggested.

3 голосов
/ 10 февраля 2017

Моя проблема, казалось, была связана с привязкой команд - я использовал RelayCommand, как часто делаю, но рендеринг кнопки просто не был корректным, пока я не нажал на окно.

Удаление кода CanExecute из CommandBinding и использование свойства IsEnabled вместо этого решило мою проблему без головной боли - это заняло целую вечность, пока я не попробовал это среди многих других вещей, которые могли быть проблемой.

0 голосов
/ 20 апреля 2016

Иногда при установке фокуса на родительский элемент управления CommandManager запускает CanExecute. Попробуйте следующее после установки Running to false:

...
Running = false;
parentControl.Focusable = true;
parentControl.Focus();
...