Hooking into CommandManager.PreviewExecuted event from VM

Aug 5, 2010 at 12:08 AM

Hi,

I am trying to figure out how I can hook into the CommandManager.PreviewExecuted event from my ViewModel.  I would like to intercept the delete event for a DataGrid to allow the user to accept/cancel their action.

Cheers,
Scott

Aug 5, 2010 at 12:59 AM

I think that I may have figured out.  I have created a CommandManagerTrigger to me to hook in.  Below is th code if it helps people out.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace CustomTriggers
{
    public enum CommandManagerEvent
    {
        CanExecute,
        Executed,
        PreviewCanExecute,
        PreviewExecuted
    }

    public class CommandManagerTrigger : TriggerBase<FrameworkElement>
    {
        public static readonly DependencyProperty EventNameProperty = 
            DependencyProperty.Register( "Event", typeof( CommandManagerEvent ), typeof( CommandManagerTrigger ), new PropertyMetadata( null ) );

        [Category( "CommandManager Properties" )]
        public CommandManagerEvent Event
        {
            get { return (CommandManagerEvent)GetValue( EventNameProperty ); }
            set { SetValue( EventNameProperty, value ); }
        }

        protected override void OnAttached()
        {
            base.OnAttached();

            switch( Event )
            {
                case CommandManagerEvent.CanExecute:
                    CommandManager.AddCanExecuteHandler( AssociatedObject, OnCanExecute );
                    break;

                case CommandManagerEvent.Executed:
                    CommandManager.AddExecutedHandler( AssociatedObject, OnExecuted );
                    break;

                case CommandManagerEvent.PreviewCanExecute:
                    CommandManager.AddPreviewCanExecuteHandler( AssociatedObject, OnPreviewCanExecute );
                    break;

                case CommandManagerEvent.PreviewExecuted:
                    CommandManager.AddPreviewExecutedHandler( AssociatedObject, OnPreviewExecuted );
                    break;
            }
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            switch( Event )
            {
                case CommandManagerEvent.CanExecute:
                    CommandManager.RemoveCanExecuteHandler( AssociatedObject, OnCanExecute );
                    break;

                case CommandManagerEvent.Executed:
                    CommandManager.RemoveExecutedHandler( AssociatedObject, OnExecuted );
                    break;

                case CommandManagerEvent.PreviewCanExecute:
                    CommandManager.RemovePreviewCanExecuteHandler( AssociatedObject, OnPreviewCanExecute );
                    break;

                case CommandManagerEvent.PreviewExecuted:
                    CommandManager.RemovePreviewExecutedHandler( AssociatedObject, OnPreviewExecuted );
                    break;
            }
        }

        private void OnCanExecute( object sender, CanExecuteRoutedEventArgs args )
        {
            InvokeActions( args );
        }

        private void OnExecuted( object sender, ExecutedRoutedEventArgs args )
        {
            InvokeActions( args );
        }

        private void OnPreviewCanExecute( object sender, CanExecuteRoutedEventArgs args )
        {
            InvokeActions( args );
        }

        private void OnPreviewExecuted( object sender, ExecutedRoutedEventArgs args )
        {
            InvokeActions( args );
        }
    }
}

And then it is as simple as:
            <i:Interaction.Triggers>
                <assets:CommandManagerTrigger Event="PreviewExecuted">
                    <cal:ActionMessage MethodName="PreviewUserCommand">
                        <cal:ActionMessage.Parameters>
                            <cal:Parameter Value="$eventargs" />
                            <cal:Parameter Value="{Binding ElementName=UsersGrid, Path=SelectedItem}" />
                        </cal:ActionMessage.Parameters>
                    </cal:ActionMessage>
                </assets:CommandManagerTrigger>
            </i:Interaction.Triggers>

Coordinator
Aug 5, 2010 at 1:47 PM

Love it!. This might make a nice contribution to our recipes section. Would you be interested?

Aug 6, 2010 at 12:17 AM
Sure, happy to contribute. I originally was having trouble using the DataGrid and was hoping that this might solve the problems that I was facing. It did assist with one, and that was providing a notification message when a person tried to delete a row from the grid, by peeking a look at the DataGrid.DeleteCommand in the PreviewExecuted event. One thing that I did notice was that a CommandManager.Execute would not be fired unless you had a paired CommandManager.CanExecute, so I am not sure what is going on there. Cheers, Scott