Skip to main content

WPF Tutorial - Using The Built-In Commands

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 Screenshot
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

FlexBox (combobox+json +Paging)

FlexBox Visit the FlexBox Home Page FlexBox  is a jQuery plugin that is intended to be a very flexible replacement for html textboxes and dropdowns, optionally using ajax to retrieve and bind JSON data. It can be used as a: ComboBox, with optional per-result html templates Suggest box, like Google's search Data-driven type-ahead input box It supports: Auto-completion using local (JSON) or remote (JSON via ajax) data Skinning via css Flexible paging Configurable client-side caching Much more... (see Configuration Options in the documentation) Screenshotflex More demos and code examples

ASP .NET - XML Files

An XML File Here is an XML file named "countries.xml": <?xml version="1.0" encoding="ISO-8859-1"?> <countries> <country>   <text>Norway</text>   <value>N</value> </country> <country>   <text>Sweden</text>   <value>S</value> </country> <country>   <text>France</text>   <value>F</value> </country> <country>   <text>Italy</text>   <value>I</value> </country> </countries> Bind a DataSet to a List Control First, import the "System.Data" namespace. We need this namespace to work with DataSet objects. Include the following directive at the top of an .aspx page: <%@ Import Namespace="System.Data" %> Next, create a DataSet for the XML file and load the XML file into the DataSet when the page is first loaded: <script runat="server"> sub Page_Load if Not Page.IsPos...

SQL JOINS &UNION

SQL JOIN The JOIN keyword is used in an SQL statement to query data from two or more tables, based on a relationship between certain columns in these tables. Tables in a database are often related to each other with keys. A primary key is a column (or a combination of columns) with a unique value for each row. Each primary key value must be unique within the table. The purpose is to bind data together, across tables, without repeating all of the data in every table. Look at the "Persons" table: P_Id LastName FirstName Address City 1 Hansen Ola Timoteivn 10 Sandnes 2 Svendson Tove Borgvn 23 Sandnes 3 Pettersen Kari Storgt 20 Stavanger Note that the "P_Id" column is the primary key in the "Persons" table. This means that  no  two rows can have the same P_Id. The P_Id distinguishes two persons even if they have the same name. Next, we have the "Orders" table: O_Id OrderNo P_Id 1 77895 3 2 44678 3 3 22456 1 4 24562 1 5 34764 15 Note that the "O_...