我刚刚更新了一个从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);
获取can执行状态以重新评估。对于如上所述的DataWindowButton,我不得不在按钮的命令上手动调用RaiseCanExecuteChanged,因为据我所知,该命令不属于vie模型。
var catelCommand = (applyButton.Command as ICatelCommand);
if (catelCommand != null)
{
catelCommand.RaiseCanExecuteChanged();
}
在任何一种情况下,这都不是具有最佳性能特征的方法,但如果需要升级前的相同行为,则可以在以下事件订阅中进行这些调用:
System.Windows.Input.CommandManager.RequerySuggested += RequerySuggested;
希望这可以帮助其他任何人面对这个问题。
答案 0 :(得分:2)
原因在于,在过去(4.0版之前),Catel订阅了WPF的CommandManager,并在几乎所有内容(鼠标移动,焦点等)上使所有视图模型上的所有命令无效。为了提高性能(很多),我们决定仅在特定视图模型上的属性更改时自动使命令无效。
例如,如果您有更改属性的虚拟机,它将自动重新评估该虚拟机上的命令。您仍然可以使用此代码手动重新评估命令(在vm中):
ViewModelCommandManager.InvalidateCommands(true);
答案 1 :(得分:1)
这个怎么样?我有一个问题,我的嵌套用户控件必须导致我的外部用户控件的命令更新。它并不优雅,但它可以为我完成工作,直到我能够获得更好的方式。
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);
}
}
}