在研究了几个Q & A o n s tackoverflow,s ome t utorials后,当然还有o fficial d ocumentation,我尝试在我的WPF Prism MVVM应用程序中使用ApplicationCommands
。
我目前的做法
在尝试了不同的解决方案之后我发现了,我最终得到了以下星座:
我正在使用this answer中提到的AttachCommandBindingsBehavior
类,它将在视图中使用,如下所示:
<UserControl>
<i:Interaction.Behaviors>
<localBehaviors:AttachCommandBindingsBehavior CommandBindings="{Binding CommandBindings}"/>
</i:Interaction.Behaviors>
</UserControl>
MyViewModel
包含CommandBindingCollection
属性,该属性将填充在构造函数中:
public CommandBindingCollection CommandBindings { get; } = new CommandBindingCollection();
public MyViewModel()
{
this.CommandBindings.AddRange(new[]
{
new CommandBinding(ApplicationCommands.Save, this.Save, this.CanSave),
new CommandBinding(ApplicationCommands.Open, this.Open)
});
}
UserControl MyView
包含两个按钮:
<Button Command="ApplicationCommands.Open" Content="Open" />
<Button Command="ApplicationCommands.Save" Content="Save" />
此时的第一个问题是:Executed()
和CanExecute()
方法是否已绑定到Button
的Command-DependencyProperty?既然它不起作用,我忘了或做错了什么?
我的第二个问题是:如何触发按钮绑定的命令的CanExecute
?当用户成功执行MyViewModel.CanSave()
方法时,实际用例:MyViewModel.Open()
返回true。通常,我会拨打DelegateCommand.RaiseCanExecuteChanged()
,但是调用ApplicationCommands.Save.RaiseCanExecuteChanged()
不会执行MyViewModel.CanSave()
。
随时询问更多信息。我将非常感谢你的回答。谢谢!
答案 0 :(得分:1)
既然它不起作用,我忘记了什么或做错了什么?
您行为的CommandBindings
属性为ObservableCollection<CommandBinding>
,但您可以将其绑定到视图模型中的CommandBindingCollection
。将您的视图模型的属性更改为ObservableCollection<CommandBinding>
。
您链接的AttachCommandBindingsBehavior
也存在一些问题。我不确定为什么答案被接受了,因为它确实很破碎。不过,下面的调整版本应该可行。
public class AttachCommandBindingsBehavior : Behavior<FrameworkElement>
{
public ObservableCollection<CommandBinding> CommandBindings
{
get => (ObservableCollection<CommandBinding>)GetValue(CommandBindingsProperty);
set => SetValue(CommandBindingsProperty, value);
}
public static readonly DependencyProperty CommandBindingsProperty =
DependencyProperty.Register(
"CommandBindings",
typeof(ObservableCollection<CommandBinding>),
typeof(AttachCommandBindingsBehavior),
new PropertyMetadata(null, OnCommandBindingsChanged));
private static void OnCommandBindingsChanged(
DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
var b = sender as AttachCommandBindingsBehavior;
if (b == null)
return;
var oldBindings = e.OldValue as ObservableCollection<CommandBinding>;
if (oldBindings != null)
oldBindings.CollectionChanged -= b.OnCommandBindingsCollectionChanged;
var newBindings = e.OldValue as ObservableCollection<CommandBinding>;
if (newBindings != null)
newBindings.CollectionChanged += b.OnCommandBindingsCollectionChanged;
b.UpdateCommandBindings();
}
protected override void OnAttached()
{
base.OnAttached();
UpdateCommandBindings();
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.CommandBindings.Clear();
}
private void UpdateCommandBindings()
{
if (AssociatedObject == null)
return;
AssociatedObject.CommandBindings.Clear();
if (CommandBindings != null)
AssociatedObject.CommandBindings.AddRange(CommandBindings);
CommandManager.InvalidateRequerySuggested();
}
private void OnCommandBindingsCollectionChanged(
object sender,
NotifyCollectionChangedEventArgs e)
{
UpdateCommandBindings();
}
}
如何触发按钮绑定的命令的CanExecute?
您可以建议 WPF的路由命令系统通过调用CommandManager.InvalidateRequerySuggested()
重新评估所有命令。实际的重新评估将以Background
调度程序优先级异步发生。这是明确的方法,但您应该知道,某些操作已经发生隐式,例如焦点更改和鼠标/键盘按钮事件。 WPF开发人员试图尽可能无缝地进行自动命令重新查询,因此它只是工作&#34;大多数时候。
实际用例:
MyViewModel.CanSave()
返回true
[...]
为了清楚起见,作为CanExecuteRoutedEventHandler
,您的CanSave
方法应返回void
并在事件参数上将CanExecute
设置为true
。