Wednesday, March 24, 2010

WPF Command bindings - Mouse clicks

The following article discusses the WPF command binding feature with relation to Mouse clicks.

One of WPF powerful features is the binding of commands to controls. If you have used the MVVM design pattern, you will know how useful, powerful, easy, efficient and robust the application gets with WPF commands.

A simple scenario of a command binding would be,

<Window>
<Window.CommandBindings>
    <CommandBinding Command="Help" 
       CanExecute="TestCommandCanExecute"
       Executed="TestCommandExecute" />
 </Window.CommandBindings>
<Grid>
 <Button Command="Help" Content="Click me" />
</Grid>
</Window>


When the button is clicked, first TestCommandCanExecute will be invoked and then as usual TestCommandExecute.

In addition to the simple scenarios of binding a command to a click event we also need to bind specific commands to specific events. For e.g., how about binding one command to Right Click and other to Left click ?
No problems at all. We can use the Mouse bindings to bind a specific command to a specific Mouse event.

Something like this,

<Button Content="Click Me">
    <Button.InputBindings>
        <MouseBinding Command="TestCommandLeft" MouseAction="RightClick" />
        <MouseBinding Command="TestCommandRight" MouseAction="RightClick" />
    </Button.InputBindings>
</Button>


The other Mouse actions supported for Mouse bindings are - LeftClick, RightClick, MiddleClick, WheelClick, LeftDoubleClick, RightDoubleClick, MiddleDoubleClick

I have attached an application demonstrating this behavior.

Here is the XAML,

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:WpfApplication1"
    Title="Window1" Height="300" Width="300">
    
    <Window.CommandBindings>
        <CommandBinding Command="{x:Static custom:Window1.SimpleCommand}" CanExecute="SimpleCanExecute" Executed="SimpleExecute" />
        <CommandBinding Command="{x:Static custom:Window1.LeftClickCommand}" CanExecute="LeftClickCanExecute" Executed="LeftClickExecute" />
        <CommandBinding Command="{x:Static custom:Window1.RightClickCommand}" CanExecute="RightClickCanExecute" Executed="RightClickExecute" />
    </Window.CommandBindings>
    
    <StackPanel Orientation="Vertical" >
        <Button Content="Simple command" Command="{x:Static custom:Window1.SimpleCommand}">           
        </Button>
        <Button Content="Complex command">
            <Button.InputBindings>
                <MouseBinding Command="{x:Static custom:Window1.LeftClickCommand}" MouseAction="LeftClick" />
                <MouseBinding Command="{x:Static custom:Window1.RightClickCommand}" MouseAction="RightClick" />
            </Button.InputBindings>
        </Button>       
    </StackPanel>
</Window>


This is the code behind,

using System.Windows;
using System.Windows.Input;

namespace WpfApplication1
{
    /// 
    /// Interaction logic for Window1.xaml
    /// 
    public partial class Window1 : Window
    {
        public static RoutedCommand SimpleCommand = new RoutedCommand();
        public static RoutedCommand LeftClickCommand = new RoutedCommand();
        public static RoutedCommand RightClickCommand = new RoutedCommand();

        public Window1()
        {
            InitializeComponent();
        }

        private void SimpleCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
            e.Handled = true;
        }

        private void SimpleExecute(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("Simple Command");
            e.Handled = true;
        }

        private void LeftClickCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
            e.Handled = true;
        }

        private void LeftClickExecute(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("Left click");
            e.Handled = true;
        }

        private void RightClickCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
            e.Handled = true;
        }

        private void RightClickExecute(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("Right click");
            e.Handled = true;
        }
    }
}