在WPF PRISM中使用ApplicationCommands [英] Using ApplicationCommands in WPF PRISM

查看:50
本文介绍了在WPF PRISM中使用ApplicationCommands的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

研究了几个 Q & n s tackoverflow,s ome t

After studying several Q&A on stackoverflow, some tutorials and of course the official documentation, I trying to use ApplicationCommands in my WPF Prism MVVM application.

我目前的做法

尝试了各种不同的解决方案后,我得到了以下星座:

After trying different solutions I found out, I ended up with following constellation:

  1. 我正在使用此答案中提到的 AttachCommandBindingsBehavior 类在视图中像这样使用:

  1. I am using the AttachCommandBindingsBehavior class mentioned in this answer, which will be used like this in the view:

<UserControl>
    <i:Interaction.Behaviors>
        <localBehaviors:AttachCommandBindingsBehavior CommandBindings="{Binding CommandBindings}"/>
    </i:Interaction.Behaviors>
</UserControl>

  • MyViewModel 包含一个 CommandBindingCollection 属性,该属性将在构造函数中填充:

  • MyViewModel contains a CommandBindingCollection property, which will be populated in the constructor:

    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 ?既然不起作用,我忘记了什么或弄错了什么?

    My first question at this point is: Are the Executed() and CanExecute() methods already bound to the Command-DependencyProperty of the Button? Since it does not work, what did I forgot or made wrong?

    我的第二个问题是:如何触发按钮绑定到的命令的 CanExecute ?实际用例:当用户成功执行 MyViewModel.Open()方法时, MyViewModel.CanSave()返回true.通常,我会调用 DelegateCommand.RaiseCanExecuteChanged(),但是调用 ApplicationCommands.Save.RaiseCanExecuteChanged()不会执行 MyViewModel.CanSave()

    My second question is: How can I trigger the CanExecute of the Command the Button is bound to? The actual use-case: MyViewModel.CanSave() returns true, when the user successfully executed the MyViewModel.Open() method. Usually, I would call an DelegateCommand.RaiseCanExecuteChanged(), but calling ApplicationCommands.Save.RaiseCanExecuteChanged() does not execute MyViewModel.CanSave().

    随时询问更多信息.非常感谢您的回答.谢谢!

    Feel free to ask for more information. I will really appreciate your answers. Thank you!

    推荐答案

    由于它不起作用,我忘记了什么或弄错了什么?

    Since it does not work, what did I forgot or made wrong?

    您行为的 CommandBindings 属性是 ObservableCollection< CommandBinding> ,但是您将其绑定到视图模型中的 CommandBindingCollection .将视图模型的属性更改为 ObservableCollection< CommandBinding> .

    The CommandBindings property on your behavior is an ObservableCollection<CommandBinding>, but you're binding it to a CommandBindingCollection in your view model. Change your view model's property to a ObservableCollection<CommandBinding>.

    您链接到的 AttachCommandBindingsBehavior 也存在一些问题.我不知道为什么答案会被接受,因为它实际上是很糟糕的.不过,下面经过调整的版本应该可以使用.

    There are also some problems with the AttachCommandBindingsBehavior you linked to. I'm not sure why the answer was accepted, because it's actually quite broken. The tweaked version below should work, though.

    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.NewValue 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?

    How can I trigger the CanExecute of the Command the Button is bound to?

    您可以建议 WPF的路由命令系统通过调用 CommandManager.InvalidateRequerySuggested()重新评估所有命令.实际的重新评估将以 Background 调度程序的优先级异步进行.这是一种明确的方法,但是您应该知道,在某些操作(例如焦点更改和鼠标/键盘按钮按下事件)上已经隐式发生了这种情况.WPF开发人员试图使自动命令重新查询尽可能地无缝,因此它工作正常".大部分时间.

    You can suggest that WPF's routed command system reevaluate all commands by calling CommandManager.InvalidateRequerySuggested(). The actual reevaluation will occur asynchronously at the Background dispatcher priority. This is the explicit way to do it, but you should know that this already happens implicitly upon certain actions, like focus changes and mouse/keyboard button-up events. The WPF developers tried to make automatic command requerying as seamless as possible, so it "just works" most of the time.

    实际用例: MyViewModel.CanSave()返回 true [...]

    请注意,作为 CanExecuteRoutedEventHandler ,您的 CanSave 方法应返回 void 并将 CanExecute 设置为事件参数为 true .

    Just to be clear, as a CanExecuteRoutedEventHandler, your CanSave method should return void and set CanExecute to true on the event argument.

    这篇关于在WPF PRISM中使用ApplicationCommands的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆