Skip to main content

C# - Using The Built-In Commands WPF [Beginner]


One of the features that WPF has is actually a blast from the past - something that MFC used to have, but was never included in WinForms. This is the concept of Commands. Commands are somewhat like events in that they are based on actions in the user interface, a command can get triggered (just like an event). But unlike regular events like 'click', commands are built in a way that makes it very easy to expose the same functionality at multiple places in an interface, with very little code duplication.

On of the very useful features of commands is the fact that you actually get an automatic form of two way communication between the interface elements and the command they are bound too. This is because a command is made up of two main elements - Execute and CanExecute. So unlike in the regular world of events, when an action becomes unavailable, you can just have the CanExecute part of the command return false - and everything hooked to that command becomes disabled. Without this, you would have to do any of a number of ugly things to make sure that all user interface elements that perform an action are always correctly enabled or disabled.

Today we are going to take a look at how to use the built in commands that WPF provides (and there are a lot of them). The handy thing about the built in commands is that a number of the standard controls automatically respond to them. Take a look at the XAML code below:
<Window x:Class="SimpleTextEditor.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="CommandTest" Height="300" Width="318">
  <Window.Resources>
    <Style TargetType="{x:Type Button}" x:Key="textBoxCommands">
      <Setter Property="Content" Value=
          "{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}" />
      <Setter Property="CommandTarget" Value="{Binding ElementName=textBox}" />
    </Style>
  </Window.Resources>
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <StackPanel Orientation="Horizontal" Grid.Row="0">
      <Button Command="Cut" Style="{StaticResource textBoxCommands}" />
      <Button Command="Copy" Style="{StaticResource textBoxCommands}" />
      <Button Command="Paste" Style="{StaticResource textBoxCommands}" />
      <Button Command="AlignCenter" Style="{StaticResource textBoxCommands}" />
      <Button Command="AlignLeft" Style="{StaticResource textBoxCommands}" />
      <Button Command="AlignRight" Style="{StaticResource textBoxCommands}" />
      <Button Command="Undo" Style="{StaticResource textBoxCommands}" />
    </StackPanel>

    <RichTextBox Grid.Row="1" Name="textBox" 
        HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
  </Grid>
</Window>
 
Essentially, what we have here is a set of buttons in one row that operate on the RichTextBox below them. Here is a simple screenshot of what this looks like:

Command App

Because of these commands, there is no actual code behind required - and really, the buttons know virtually nothing about the rich text box. If you grab the xaml and compile and play with it, you might notice something really cool - the buttons even become enabled and disabled appropriately. For instance, if you have nothing selected in the text box, the Copy and Cut buttons will be disabled, but as soon as you select something, the buttons will automatically enable.

The two important properties that are being set on each button are Command and CommandTarget. The Command property specifies what command should be executed when the button is clicked. This is different for each button, because each button causes a different command to be executed. The Command property can be written in two forms for built in commands - the short form that you saw above (like Command="Paste"), or the long form: Command="{x:Static ApplicationCommands.Paste}". The short form can only be used for the built in commands, because WPF knows where they are. For the commands used above, Cut, Copy, Paste, and Undo are all in the ApplicationCommands class, and AlignCenter, AlignLeft, and AlignRight are all in the EditingCommands class. There are a a couple of other built in command classes as well: NavigationCommands, MediaCommands, and ComponentCommands.

OK, now onto the CommandTarget. The command target specifies what element the command is going to be executed on. In the case of these buttons, the target is always the textBox, which is why the target is factored out into that textBoxCommands style in the window resources. If the command target is not set, the command will just bubble up in the application until it hits some parent that watches for that command (if there is no such parent, the command does nothing and in fact will always be disabled). So, for instance, if you somehow place one of these buttons inside the texbox, you wouldn't need to set the target, because the command would bubble up and the textbox would grab it.

The only item left in the XAML above that still needs to be explained is what is being done with the Button Content property. Well, every command has a Text field on it which should contain a readable name for the command, so why not use that as the text on the button instead of explicitly setting the content to something like "Cut"? That is what that binding is doing in the style - it is grabbing the Text property off of the command attached to the button, and setting that text as the content of the button.

Well, that is all for this introduction to WPF commands. I'll be back soon with a tutorial on how to write and use your own WPF commands - and that is where the real power comes in.

Comments

Popular posts from this blog

C# Snippet - Shuffling a Dictionary [Beginner]

Randomizing something can be a daunting task, especially with all the algorithms out there. However, sometimes you just need to shuffle things up, in a simple, yet effective manner. Today we are going to take a quick look at an easy and simple way to randomize a dictionary, which is most likely something that you may be using in a complex application. The tricky thing about ordering dictionaries is that...well they are not ordered to begin with. Typically they are a chaotic collection of key/value pairs. There is no first element or last element, just elements. This is why it is a little tricky to randomize them. Before we get started, we need to build a quick dictionary. For this tutorial, we will be doing an extremely simple string/int dictionary, but rest assured the steps we take can be used for any kind of dictionary you can come up with, no matter what object types you use. Dictionary < String , int > origin = new Dictionary < string , int >(); ...

C# WPF Printing Part 2 - Pagination [Intermediate]

About two weeks ago, we had a tutorial here at SOTC on the basics of printing in WPF . It covered the standard stuff, like popping the print dialog, and what you needed to do to print visuals (both created in XAML and on the fly). But really, that's barely scratching the surface - any decent printing system in pretty much any application needs to be able to do a lot more than that. So today, we are going to take one more baby step forward into the world of printing - we are going to take a look at pagination. The main class that we will need to do pagination is the DocumentPaginator . I mentioned this class very briefly in the previous tutorial, but only in the context of the printing methods on PrintDialog , PrintVisual (which we focused on last time) and PrintDocument (which we will be focusing on today). This PrintDocument function takes a DocumentPaginator to print - and this is why we need to create one. Unfortunately, making a DocumentPaginator is not as easy as...

C# WPF Tutorial - Implementing IScrollInfo [Advanced]

The ScrollViewer in WPF is pretty handy (and quite flexible) - especially when compared to what you had to work with in WinForms ( ScrollableControl ). 98% of the time, I can make the ScrollViewer do what I need it to for the given situation. Those other 2 percent, though, can get kind of hairy. Fortunately, WPF provides the IScrollInfo interface - which is what we will be talking about today. So what is IScrollInfo ? Well, it is a way to take over the logic behind scrolling, while still maintaining the look and feel of the standard ScrollViewer . Now, first off, why in the world would we want to do that? To answer that question, I'm going to take a an example from a tutorial that is over a year old now - Creating a Custom Panel Control . In that tutorial, we created our own custom WPF panel (that animated!). One of the issues with that panel though (and the WPF WrapPanel in general) is that you have to disable the horizontal scrollbar if you put the panel in a ScrollV...