更新到Catel 4.4.0后,CanExecute命令方法未触发

时间:2016-02-09 21:18:38

标签: c# wpf mvvm catel

我最近将我的应用程序从Catel 3.9.0更新到4.4.0。除了出现在我的大多数视图中的“打印”按钮之外,事情通常都很顺利。

应用程序允许客户选择并加载文本文件,然后对其进行解析和验证。如果有任何错误,它们将显示在网格控件的视图中。显示任何错误还应启用“打印”按钮,让客户预览并打印错误报告。

View架构是:

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

ErrorsAndWarningsGrid绑定到关联ViewModel的公共父类中的ObservableCollection。此ObservableCollection包含包含验证错误/警告的对象。

此外,View是一个打印按钮,绑定到公共父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),但我关心的是是否有更好/更简单的解决方案。

如果您有任何疑问或需要更多信息,请告诉我们。谢谢!

1 个答案:

答案 0 :(得分:0)

出于性能原因,Catel不再自动订阅CommandManager以使状态无效(保存CanExecute调用的 lot )。如果您想要恢复所有这些行为,您可以创建一个自定义类,订阅命令managerand并使命令无效。

2免责声明

  1. 由于某种原因(性能)已将其删除,因此这不是推荐的方法。但这可以让你恢复旧的行为。
  2. 我没有测试过这段代码,但它几乎可以开箱即用。
  3. <强>代码

    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();
                }
            }
        }
    }