C# DataWindowButton可执行不点火,Catel 4.0

C# DataWindowButton可执行不点火,Catel 4.0,c#,wpf,catel,C#,Wpf,Catel,我刚刚将一个项目从Catel 3.4更新为Catel 4.0,一个一直在工作的自定义应用按钮现在从未启用 AddCustomButton(new DataWindowButton("Apply", ExecuteApply, canExecuteApply)); 在Catel 3.4中,当窗口获得焦点或任何控件发生更改时,会调用canExecuteApply。在4.0中,创建窗口时会调用它两次,以后再也不会调用 我怀疑这与更新指南的IViewPropertySelector部分有关,但是注册默

我刚刚将一个项目从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;

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

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

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


这个怎么样?我遇到一个问题,嵌套的用户控件必须导致外部用户控件的命令更新。它并不优雅,但它能帮我完成任务,直到我找到更好的方法

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);
        }
    }
}
公共部分类应用程序:应用程序
{
专用静态IViewModelManager\u ViewModelManager;
公共应用程序()
:base()
{
var dependencyrolver=this.getdependencyrolver();
_ViewModelManager=dependencyResolver.Resolve();
System.Windows.Input.CommandManager.RequerySuggested+=RequerySuggested;
}
建议的私有void重新查询(对象发送方,事件参数e)
{
foreach(ViewModelManager.ActiveViewModels中的IViewModel viewModel)
{
(viewModel作为ViewModelBase).GetViewModelCommandManager().InvalidateCommand(true);
}
}
}

对于视图模型中的显式AsynchronousCommand实例,这是有效的。在System.Windows.Input.CommandManager.RequerySuggest的订阅中执行此操作,以恢复这些虚拟机的旧行为。但是,我在哪里为DataWindowButton执行此操作呢?从我的头顶上看,它确实实现了相同的逻辑。否则请查看源代码,这就是开源的力量;-)那么,如果您有一个嵌套的usercontrol,并且当用户控件的属性发生更改时,outher视图上的命令必须无效,您会有什么建议呢。。。请看我的答案,告诉我你的想法。在我找到这个之前,我一直在发疯。这也是一个有效的解决方案。请确保这不会对性能造成太大影响。是的,我确实注意到了一个轻微的性能问题,但没有太大影响。如果我理解正确,只有活动的viewmodels会受到影响,但这与v4.0之前的工作方式有什么不同吗?问题是,RequestSugged被频繁触发(我是说频繁)。我们在Catel 4.0中更改此行为是有原因的(之前在命令上使用RequerySuggest)。
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);
        }
    }
}