DataWindowButton CanExecute 未触发,Catel 4.0

Posted

技术标签:

【中文标题】DataWindowButton CanExecute 未触发,Catel 4.0【英文标题】:DataWindowButton CanExecute not firing, Catel 4.0 【发布时间】:2014-11-18 22:24:32 【问题描述】:

我刚刚将一个项目从 Catel 3.4 更新到 Catel 4.0,并且现在一直在工作的自定义应用按钮从未启用。

AddCustomButton(new DataWindowButton("Apply", ExecuteApply, canExecuteApply));

在 Catel 3.4 中,当窗口获得焦点或任何控件发生更改时,会调用 canExecuteApply。在 4.0 中,它在创建窗口时被调用两次,并且不再调用。

我怀疑这与更新指南的 IViewPropertySelector 部分有关,但是注册默认实现没有效果,我无法弄清楚 AutoDetectViewPropertiesToSubscribe 扩展方法位于哪个命名空间。

编辑:我发现我在应用程序其他地方的一些 AsynchronousCommand 实例中得到了相同的行为。 CanExecute 委托在创建控件时触发,然后再也不会触发。

编辑 2:这些是不同解决方案的相同问题。有关该问题的解释,请参阅 Geert van Horrik 的回答。

如果命令在视图模型中注册,您可以使用

ViewModelCommandManager.InvalidateCommands(true);

获取可执行状态以重新评估。对于如上所述的 DataWindowButton,我必须在按钮的命令上手动调用 RaiseCanExecuteChanged,因为据我所知,该命令不属于 vie 模型。

var catelCommand = (applyButton.Command as ICatelCommand);
if (catelCommand != null)

    catelCommand.RaiseCanExecuteChanged();

在任何一种情况下,这都远不是具有最佳性能特征的方法,但如果需要升级之前的相同行为,您可以在以下事件订阅中进行这些调用:

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

希望这可以帮助其他面临此问题的人。

【问题讨论】:

【参考方案1】:

原因是在过去(4.0 之前),Catel 订阅了 WPF 的 CommandManager,并在几乎所有内容(鼠标移动、焦点等)上使所有视图模型上的所有命令无效。为了提高性能(很多),我们决定仅在特定视图模型上的属性更改时自动使命令无效。

例如,如果您有一个 vm 并在其中更改了属性,它将自动重新评估该 vm 上的命令。您仍然可以使用此代码(在 vm 内)手动重新评估命令:

ViewModelCommandManager.InvalidateCommands(true);

【讨论】:

对于视图模型中的显式 AsynchronousCommand 实例,这是可行的。是否在订阅 System.Windows.Input.CommandManager.RequerySuggested 以恢复这些虚拟机的旧行为。但是,我在哪里为 DataWindowButton 执行此操作? 在我看来,它确实实现了相同的逻辑。否则请查看源代码,这就是开源的力量;-) 那么,如果您有一个嵌套的用户控件,并且当用户控件的属性发生更改时,外部视图上的命令必须失效,您会建议什么? 我玩了一会儿,找到了另一种方法......请看我的回答并告诉我你的想法。 在找到这个之前,我已经疯了好几个小时了。【参考方案2】:

这个怎么样?我有一个问题,我的嵌套用户控件必须导致我的外部用户控件的命令更新。它并不优雅,但它可以为我完成工作,直到我找到更好的方法。

public partial class App : Application


    private static IViewModelManager _ViewModelManager;

    public App()
        : base()
    
        var dependencyResolver = this.GetDependencyResolver();

        _ViewModelManager = dependencyResolver.Resolve<IViewModelManager>();

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

    private void RequerySuggested(object sender, EventArgs e)
    
        foreach (IViewModel viewModel in _ViewModelManager.ActiveViewModels)
        
            (viewModel as ViewModelBase).GetViewModelCommandManager().InvalidateCommands(true);
        
    

【讨论】:

这也是一个可行的解决方案。只要确保这不会对性能产生太大影响。 是的,我确实注意到了轻微的性能问题,但并不多。如果我理解正确,只有活动的视图模型应该受到影响,但这与 v4.0 之前的工作方式有什么不同吗? 问题是 RequestSuggested 被解雇了很多(我的意思是 lot)。我们在 Catel 4.0 中更改此行为是有原因的(之前在命令上使用了 RequerySuggested)。

以上是关于DataWindowButton CanExecute 未触发,Catel 4.0的主要内容,如果未能解决你的问题,请参考以下文章