2016-02-09 2 views
0

Я недавно обновил приложение от Catel 3.9.0 до 4.4.0. Вещи, как правило, хорошо работают, за исключением кнопки «Печать», которая появляется на большинстве моих просмотров.Метод CanExecute команды не запускается после обновления до Catel 4.4.0

Приложение позволяет Заказчику выбирать и загружать текстовый файл, который затем анализируется и проверяется. Если есть какие-либо ошибки, они отображаются в представлении в элементе управления сеткой. При отображении любых ошибок также следует включить кнопку «Печать», чтобы позволить клиенту просмотреть и распечатать отчет об ошибках.

The View архитектура:

MyView.xaml (Catel UserControl) 
    CommonErrorsWarnings.xaml (Catel UserControl) 
     ErrorsAndWarningsGrid (DevExpress GridControl) 

ErrorsAndWarningsGrid привязан к ObservableCollection в общий родительский класс ассоциированного ViewModel. Этот ObservableCollection содержит объекты, содержащие ошибки проверки/предупреждения.

Также в представлении «Просмотр» есть кнопка «Печать», привязанная к команде в общем родительском классе ViewModel. Она имеет следующий «может выполнить» метод:

/// <summary> 
/// Method to check whether the PrintReport command can be executed. 
/// </summary> 
/// <returns><c>true</c> if the command can be executed; otherwise <c>false</c></returns> 
protected virtual bool OnPrintReportCanExecute() 
{ 
    Debug.Print(string.Format("OnPrintReportCanExecute called in [{0}]. Errors/Warnings count = {1}", this.Title, this.RecordErrorsAndWarnings.Count)); 
    return this.RecordErrorsAndWarnings != null && this.RecordErrorsAndWarnings.Count > 0; 
} 

(Заявление Debug.Print просто, чтобы помочь знать, когда этот метод называется.)

Все это было прекрасно работать в Catel 3.9.0 - когда Клиент загрузил текстовый файл и ошибки проверки были добавлены в коллекцию RecordErrorsAndWarnings, кнопка «Печать» была включена. После перехода на 4.4.0 он перестает работать. Метод OnPrintReportCanExecute не вызывается так часто, как в 3.9.0, и никогда, когда счет RecordErrorsAndWarnings больше 0. Кажется, метод CanExecute не вызывается во время/после обновления коллекции. Кажется, он вызывается только тогда, когда коллекция сначала «устанавливается» при создании ViewModel, но не тогда, когда коллекция «получает», чтобы добавлять к ней элементы.

Я пробовал некоторые предложения в Catel documentation: вручную добавляя интересные свойства и регистрируя ViewPropertySelector, но ни один из них не работает.

Временное решение (из другого SO question) - вызвать ViewModelCommandManager.InvalidateCommands (true) после обновления коллекции, но моя проблема заключается в том, есть ли лучшее/более простое решение.

Если у вас есть какие-либо вопросы или вам нужна дополнительная информация, пожалуйста, дайте мне знать. Благодаря!

ответ

0

По соображениям производительности Catel больше не автоматически подписывается на CommandManager, чтобы аннулировать состояние (экономит лот вызовов CanExecute). Если вы хотите вернуть все это поведение, вы можете создать пользовательский класс, который подписывается на диспетчер команд и делает недействительными команды для вас.

2 дисклеймеры

  1. Это было удалено по причине (производительности), так что это не рекомендуемый подход. Но это позволяет вам вернуть прежнее поведение.
  2. Я не тестировал этот код, но он должен работать почти из коробки.

Код

public class RequeryAllTheThings 
{ 
    private IViewModelManager _viewModelManager; 

    public RequeryAllTheThings(IViewModelManager viewModelManager) 
    { 
     Argument.IsNotNull(() => viewModelManager); 

     _viewModelManager = viewModelManager; 

     System.Windows.Input.CommandManager.RequerySuggested += OnCommandManagerRequerySuggested; 
    } 

    private void OnCommandManagerRequerySuggested(object sender, SomeEventArgs e) 
    { 
     InvalidateCommands(); 
    } 

    private void InvalidateCommands() 
    { 
     var viewModels = _viewModelManager.ActiveViewModels; 
     foreach (var viewModel in viewModels) 
     { 
      var viewModelBase = viewModel as ViewModelBase; 
      if (viewModelBase != null) 
      { 
       var viewModelCommandManager = viewModelBase.GetViewModelCommandManager(); 
       viewModelCommandManager.InvalidateCommands(); 
      } 
     } 
    } 
} 
+0

Спасибо за ответ! Я использовал ваш класс и создавал его в своем методе App OnStartup и, похоже, работает хорошо. Я не замечаю удар производительности. Мое приложение похоже на пакетный процессор: клиент загружает текстовый файл записей, приложение обрабатывает и проверяет их, а затем приложение отображает результаты. Для клиента не так много взаимодействий. Я приурочен к работе от 1000 до 50 000 записей, и есть только добавленные 7 секунд на 50 тыс. Записей в течение 2 мин 3 с, поэтому я не слишком обеспокоен. Еще раз спасибо! – RandyB

+0

Я заметил кое-что интересное: у меня есть другое приложение, которое НЕ показывает эту проблему «может выполнить». Они работают аналогично, но в этом втором приложении ViewModel спускается непосредственно из ViewModelBase. В моем первом приложении ViewModel сходит с промежуточной виртуальной машины, которая затем спускается из ViewModelBase. Может ли это объяснить эту проблему? Просто интересуюсь. Благодарю. – RandyB

+0

Это потому, что Catel автоматически переоценивает команды при изменении свойства. Но если свойство vm не изменяется, нет причин для переоценки команд (автоматически). Вот почему вашему первому приложению нужен этот дополнительный код. –

Смежные вопросы