SYSK 346: How WPF Commands Make Programmer’s Life Easier


Yesterday, I came across the following example demonstrating the power of WPF commands written by Adam Nathan and published in his book “Windows Presentation Foundation Unleashed” (I’ve made some small formatting changes):


 


<Window x:Class=WPFWinApp.Window1


    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation


    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml 


    Title=WPFWinApp Height=300 Width=600


    >


      <StackPanel>


            <StackPanel Orientation=Horizontal>


                  <Button Command=Cut CommandTarget={Binding ElementName=tb1} Content={Binding RelativeSource={RelativeSource Self}, Path=Command.Text} />


                  <Button Command=Copy CommandTarget={Binding ElementName=tb1} Content={Binding RelativeSource={RelativeSource Self}, Path=Command.Text} />


                  <Button Command=Paste CommandTarget={Binding ElementName=tb1} Content={Binding RelativeSource={RelativeSource Self}, Path=Command.Text} />


                  <Button Command=Undo CommandTarget={Binding ElementName=tb1} Content={Binding RelativeSource={RelativeSource Self}, Path=Command.Text} />


                  <Button Command=Redo CommandTarget={Binding ElementName=tb1} Content={Binding RelativeSource={RelativeSource Self}, Path=Command.Text} />


            </StackPanel>


            <StackPanel Orientation=Horizontal>


                  <Label>Enter some text:  </Label>


                  <TextBox x:Name=tb1 Width=200 />


            </StackPanel>


      </StackPanel>


</Window>


 


Believe it or not, that’s all that’s needed to implement cut, copy, paste, undo and redo operations in WPF, including the buttons enabling/disabling themselves as needed (e.g. when nothing in clipboard, or when text not selected)!  No code behind needed!


 


Try it for yourself!  It’s pretty cool…


 


WPF defines a large number of commands – see ApplicationCommands, ComponentCommands, MediaCommands, NavigationCommands and EditingCommands – that allow developers to achieve rich interaction between controls that have no direct knowledge of each other (e.g. button and text box).


 


If you want to create your own commands, you’ll need to either implement ICommand interface or derive from RountedUICommand/RoutedCommand class.  Or easier yet, just instantiate the RoutedUICommand class as a static field and provide get property to get its reference. 


 


The UI element that wants to use your command would then set its Command property to your command’s name, set the Content property as appropriate and provide delegates for CanExecute and Executed events.


 


Here is the code sample that demonstrates that (either click on the ‘Click Me’ button or press Ctrl+Space.  Note, the logic in the CanExecute delegate only enables the command when there is some text in textbox tb1.


 


XAML:


 


<Window x:Class=WPFWinApp.Window1


    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation


    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml 


    xmlns:l=clr-namespace:WPFWinApp


    Title=WPFWinApp Height=300 Width=600


    >


      <StackPanel>


            <StackPanel Orientation=Horizontal>


                  <Button Command=Cut CommandTarget={Binding ElementName=tb1} Content={Binding RelativeSource={RelativeSource Self}, Path=Command.Text} />


                  <Button Command=Copy CommandTarget={Binding ElementName=tb1} Content={Binding RelativeSource={RelativeSource Self}, Path=Command.Text} />


                  <Button Command=Paste CommandTarget={Binding ElementName=tb1} Content={Binding RelativeSource={RelativeSource Self}, Path=Command.Text} />


                  <Button Command=Undo CommandTarget={Binding ElementName=tb1} Content={Binding RelativeSource={RelativeSource Self}, Path=Command.Text} />


                  <Button Command=Redo CommandTarget={Binding ElementName=tb1} Content={Binding RelativeSource={RelativeSource Self}, Path=Command.Text} />


            </StackPanel>


            <StackPanel Orientation=Horizontal>


                  <Label>Enter some text:  </Label>


                  <TextBox x:Name=tb1 Width=200 />


            </StackPanel>


            <StackPanel Orientation=Horizontal>


                  <Button Command=l:Window1.MyCommand Content=Click Me Width=70 />


            </StackPanel>


      </StackPanel>


     


      <Window.CommandBindings>


            <CommandBinding Command=l:Window1.MyCommand CanExecute=MyCommand_CanExecute Executed=MyCommand_Executed />


      </Window.CommandBindings>


     


      <Window.InputBindings>


            <KeyBinding Command=l:Window1.MyCommand Key=Space Modifiers=Control />


      </Window.InputBindings>


</Window>


 


 


Code-Behind:


 


using System;


 


namespace WPFWinApp


{


    public partial class Window1 : System.Windows.Window


    {


        private static System.Windows.Input.RoutedUICommand _myCommand =


            new System.Windows.Input.RoutedUICommand(“Click Me”, “MyCommand”, typeof(System.Windows.Window));


 


        public static System.Windows.Input.RoutedUICommand MyCommand


        {


            get { return _myCommand; }


        }


 


 


        public Window1()


        {


            InitializeComponent();


        }


       


        void MyCommand_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)


        {


            if (string.IsNullOrEmpty(this.tb1.Text))


                e.CanExecute = false;


            else


                e.CanExecute = true;


        }


 


        void MyCommand_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)


        {


            System.Diagnostics.Debug.WriteLine(“MyCommand_Executed”);


        }


    }


}


 


 

Comments (0)

Skip to main content