Category Archives: XAML

Basics of Command Binding Using ICommand

ICommand is used to define a command. The interface contains the following information.

public interface ICommand
{
    //has 2 methods
    void Execute(object parameter);
    bool CanExecute(object parameter);

    //1 event
    event EventHandler CanExecuteChanged;
}

ICommand interface consists of the following:

Two methods:
CanExecute : Defines the method that determines whether the command can execute in its current state.
Execute : Defines the method to be called when the command is invoked.

One Event:
CanExecuteChanged: Occurs when changes occur that affect whether or not the command should execute.

You implement the ICommand interface on a class, provide a way for command handlers to hook up, and then do the routing when the command is invoked. You also must decide what criteria you will use for determining when to raise the CanExecuteChanged event. Using custom ICommand implementations allows us to provide our own routing mechanisms, particularly ones that are not tied to the visual tree and that can support multiple command handlers. Given an instance of an ICommand, you just call Execute, and it does whatever it’s supposed to do. Except you shouldn’t call it if it’s CanExecute is false. If you want to know when CanExecute might be willing to give you a different answer, listen to the CanExecuteChanged event.

Lets try a simple hello world application using the IComand. First, declare a class derived from ICommand and name it as MyFirstCommand. Since the class MyFirstCommand is derived from ICommand, we need to implement the interface as shown below. Whenever the command is executed, it calls the Execute() method to show a Hello World message box.

public class MyFirstCommand : ICommand
{
    public void Execute(object parameter)
    {
        MessageBox.Show("Hello world");
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }
    public event EventHandler CanExecuteChanged;
}

 

Once you have an ICommand instance handy, you can give it to a Button (on the Button.Command property), and Button knows what to do with it. As the simplest example, you can do this with the previous command:

First, we need to create get the class namespace into XAML using the following code. To know more about Instantiating an Object as a resource in XAML see the link https://kishore1021.wordpress.com/2010/02/06/instantiating-an-object-as-a-resource-in-xaml/

xmlns:local="clr-namespace:CommandBinding2"

 

Create a resource in the Grid class as shown below.

<Grid.Resources>
            <local:MyFirstCommand x:Key="hwc"/>
        </Grid.Resources>

Create a button inside the grid and assign the resource we created in the above code to the button command property.

Button Content="Hello World" Height="36" HorizontalAlignment="Left" Margin="12,115,0,0" Name="button1" VerticalAlignment="Top" Width="116"
                Command="{StaticResource hwc}"/>
   

 

If you do that, you’ll notice that the Button is enabled. In the CanExecute() method, if we have not returned true, then the button would have appeared as disabled. That’s because Button knows to call CanExecute, but we haven’t specified a parameter, and recall from above that if you pass null as an argument to CanExecute it returns false. So Button has a CommandParameter property that lets you specify what will be passed to CanExecute and Execute:

Now the button is enabled, and if you click on it, you’ll see “Hello, world” in the debug output window.

This actually isn’t just a Button feature, it’s actually in the base class ButtonBase. And MenuItem is a ButtonBase. So MenuItem can use the ICommand too. If MenuItem’s Command property is set to the Static resource hwc, it will also behave the same.

Passing parameter to the Command

Lets go through the hello world code discussed above and change it a bit to use the command parameters. In the Button class, set the CommandParameter property to some text like “Hello, World” as shown in the following code.

<Button Content="Hello World" Height="36" HorizontalAlignment="Left" Margin="12,115,0,0" Name="button1" VerticalAlignment="Top" Width="116"
                CommandParameter="Hello, World"
                Command="{StaticResource hwc}"/>
    

 

In the code file, change the Execute() method to show the parameter passed to the command. Modify the CanExecute() method to return true if the command parameter contains a value otherwise return false as shown in the following code.

public class MyFirstCommand : ICommand
{
    public void Execute(object parameter)
    {
        MessageBox.Show(parameter.ToString());
    }

    public bool CanExecute(object parameter)
    {
        if (parameter != null)
            return true;
        else
            return false;
    }
    public event EventHandler CanExecuteChanged;
}

 

Run the project and see the magic yourself.

Going further with ICommand:

 

image

Figure 1: Class diagram of the participating classes

A good starting point for creating a custom command is to use delegates. A delegate already supports invocation of a target method, and it also supports multiple subscribers. In the above diagram, have a student class and a UISaveCommand class that the MainWindow uses. The idea is that when I click on Save Button as shown in Fig 2, it should call the Save() method. But the Button Command doesn’t know where the Save() method is present. So the UISaveCommand class uses the Func<>.

image

Figure 2: Output window

Step 1:

Let us create a UISaveCommand class derived from ICommand interface and implement the interface in that class as shown below. In the CanExecute() method we are checking to see if the function pointer (funcpointer) is pointing to a valid or not. If it points to a valid function, we return true otherwise return false. The Execute() method just calls the method pointed to by the function pointer (delegate).

public class UISaveCommand : ICommand
{
    public Func<int> funcpointer
    {
        get;
        set;
    }

    public bool CanExecute(object parameter)
    {
        if (funcpointer != null)
        {
            return true;
        }
        else
            return false;

        throw new NotImplementedException();
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter)
    {
        if (funcpointer != null)
        {
            funcpointer();
        }

    }
}

Func<> is declared as public delegate TResult Func<out TResult>(); It encapsulates a method that has no parameters and returns a value of the type specified by the TResult parameter. In the MainWindow class, create an object of UISaveCommand class and assign the funcpointer to Save() method as shown below. So we are binding the method present in one class from other place using Command.

public partial class MainWindow : Window
{
    Student stobj = new Student();

   public MainWindow()
    {
        InitializeComponent();
        
        UISaveCommand savecommand = new UISaveCommand();
        savecommand.funcpointer = Save;
        stobj.StudentClassCommand = savecommand;
        this.DataContext = stobj;
    }

   public int Save()
   {
       MessageBox.Show(stobj.FirstName + stobj.LastName);
       return 0;
   }
}

Then we assign the savecommand object to the Student class property of type ICommand. Following is the code of the Student class.

public class Student : INotifyPropertyChanged
    {
       public ICommand StudentClassCommand
       {
           get;
           set;
       }

        private string firstname;

        public string FirstName
        {
            get { return firstname; }
            set
            {
                firstname = value;
                OnPropertyChanged("FirstName");
            }
        }

        private string lastname;

        public string LastName
        {
            get { return lastname; }
            set
            {
                lastname = value;
                OnPropertyChanged("LastName");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        
    }

The complete code of .CS file is

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace CommandBinding2
{
    public class MyFirstCommand : ICommand
    {
        public void Execute(object parameter)
        {
            MessageBox.Show(parameter.ToString());
        }

        public bool CanExecute(object parameter)
        {
            if (parameter != null)
                return true;
            else
                return false;
        }
        public event EventHandler CanExecuteChanged;
    }

    public class UISaveCommand : ICommand
    {
        public Func<int> funcpointer
        {
            get;
            set;
        }

        public bool CanExecute(object parameter)
        {
            if (funcpointer != null)
            {
                return true;
            }
            else
                return false;

            throw new NotImplementedException();
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            if (funcpointer != null)
            {
                funcpointer();
            }

        }
    }

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Student stobj = new Student();

       public MainWindow()
        {
            InitializeComponent();
            
            UISaveCommand savecommand = new UISaveCommand();
            savecommand.funcpointer = Save;
            stobj.StudentClassCommand = savecommand;
            this.DataContext = stobj;
        }

       public UISaveCommand savecommand
       {
           get
           {
               throw new System.NotImplementedException();
           }
           set
           {
           }
       }

       public int Save()
       {
           MessageBox.Show(stobj.FirstName + stobj.LastName);
           return 0;
       }
    }

   public class Student : INotifyPropertyChanged
    {
       public ICommand StudentClassCommand
       {
           get;
           set;
       }

        private string firstname;

        public string FirstName
        {
            get { return firstname; }
            set
            {
                firstname = value;
                OnPropertyChanged("FirstName");
            }
        }

        private string lastname;

        public string LastName
        {
            get { return lastname; }
            set
            {
                lastname = value;
                OnPropertyChanged("LastName");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        
    }

    ////public class StringDelegateCommand : ICommand
    ////{
    ////    Action<string> m_ExecuteTargets = delegate { };
    ////    Func<bool> m_CanExecuteTargets = delegate { return false; };
    ////    bool m_Enabled = false;

    ////    public bool CanExecute(object parameter)
    ////    {
    ////        Delegate[] targets = m_CanExecuteTargets.GetInvocationList();
    ////        foreach (Func<bool> target in targets)
    ////        {
    ////            m_Enabled = false;
    ////            bool localenable = target.Invoke();
    ////            if (localenable)
    ////            {
    ////                m_Enabled = true;
    ////                break;
    ////            }
    ////        }
    ////        return m_Enabled;
    ////    }
        
    ////    public void Execute(object parameter)
    ////    {
    ////        if (m_Enabled)
    ////            m_ExecuteTargets(parameter != null ? parameter.ToString() : null);
    ////    }
        
    ////    public event EventHandler CanExecuteChanged = delegate { };

    ////    public event Action<string> ExecuteTargets
    ////    {
    ////        add { m_ExecuteTargets += value; }
    ////        remove { m_ExecuteTargets -= value; }
    ////    }

    ////    public event Func<bool> CanExecuteTargets
    ////    {
    ////        add { m_CanExecuteTargets += value; CanExecuteChanged(this, EventArgs.Empty); }
    ////        remove { m_CanExecuteTargets -= value; CanExecuteChanged(this, EventArgs.Empty); }
    ////    }
    ////}
}

 

The complete code of XAML file is

<Window x:Class="CommandBinding2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:local="clr-namespace:CommandBinding2"
        Title="MainWindow" Height="282" Width="474">
    <Grid Height="295" Width="440">
        <Grid.Resources>
            <local:MyFirstCommand x:Key="hwc"/>
        </Grid.Resources>

        <TextBlock Text="Enter First Name" Margin="0,0,271,261"></TextBlock>
        <TextBox Margin="175,6,12,260" Name="txtFirstName" VerticalAlignment="Center" Text="{Binding Path=FirstName}" Height="26" />
        <TextBlock Margin="0,48,324,216" VerticalAlignment="Center" Text="Enter Last Name" Height="28" />
        <TextBox Margin="175,55,12,215" Name="txtLastName" VerticalAlignment="Center" Text="{Binding Path=LastName}"/>
        <Button Margin="187,102,0,144" Content="Save"
                Command="{Binding StudentClassCommand}" />
        <Button Content="Hello World" Height="36" HorizontalAlignment="Left" Margin="12,115,0,0" Name="button1" VerticalAlignment="Top" Width="116"
                CommandParameter="Hello, World"
                Command="{StaticResource hwc}"/>
    </Grid>
</Window>

 

Attitude determines altitude. – Anonymous

Introduction to Command Binding

We have seen the abc’s of Data Binding here. If you have worked in VC++, then you are aware of some of the semantics of WPF command binding. Basically, commands are nothing but actions performed on the applications using input mechanism. commands are abstract and loosely-coupled version of events. Whereas events are tied to details about specific user actions (such as a Button being clicked or a List Item being selected), commands represent actions independent from their user interface exposure. Canonical examples of commands are Cut, Copy, and Paste. In VC++ MFC, we declare commands and then define the functions that execute the command action. Similarly, in WPF, the semantics and the object that invokes a command is separated from the logic that executes the command. This allows for multiple and disparate sources like MenuItems in a Menu, MenuItems on a Context Menu(Right Click), Buttons on a ToolBar, keyboard shortcuts(CTRL+X for Cut), and so on, to invoke the same command logic, and it allows the command logic to be customized for different targets. We used to perform similar design in VC++ too.

In VC++ MFC application, for example, the editing operations Copy, Cut, and Paste, can be invoked by using different user actions if they are implemented by using commands. An MFC application might allow a user to cut selected text by either choosing an Cut item in edit menu, or Cut in right click menu, or using a key combination, such as CTRL+X. By using commands, you can bind each type of user action to the same logic. In VC++, we assign ID’s to each command like ID_EDIT_COPY, ID_EDIT_CUT and ID_EDIT_PASTE. WPF supports similar concepts but uses a different mechanism to achieve it. By using commands, you can bind each type of user action to the same logic. Another purpose of commands is to indicate whether an action is available. To continue the example of cutting an object or text, the action only makes sense when something is selected. If a user tries to cut an object or text without having anything selected, nothing would happen. To indicate this to the user, many applications disable buttons and menu items so that the user knows whether it is possible to perform an action.

A command is any object implementing the ICommand interface (from System.Windows.Input), which defines two methods and one event:

  • Execute—The method that executes the command-specific logic
  • CanExecute—A method returning true if the command is enabled or false if it is disabled
  • CanExecuteChanged—An event that is raised whenever the value of CanExecute changes

Steps to create a Command:

  1. Say you want to create a Cut Command. We need to implement a class that implements ICommand.
  2. Call Execute from relevant event handlers (when CanExecute returns true)
  3. Handle the CanExecuteChanged event to toggle the IsEnabled property on the relevant pieces of user interface.

Fortunately, controls such as Button, CheckBox, and MenuItem have logic to interact with any command on your behalf. They expose a simple Command property (of type ICommand). When set, these controls automatically call the command’s Execute method (when CanExecute returns true) whenever their Click event is raised. In addition, they automatically keep their value for IsEnabled synchronized with the value of CanExecute by leveraging the CanExecuteChanged event. By supporting all this via a simple property assignment, all of this logic is available from XAML. Some of WPF’s controls have built-in behavior tied to various commands. 

WPF’s built-in commands like Cut, Copy, Paste are exposed as static properties and they are all instances of RoutedUICommand, a class that not only implements ICommand, but supports bubbling just like a routed event. A command can indicate whether an action is possible by implementing the CanExecute method. A button can subscribe to the CanExecuteChanged event and be disabled if CanExecute returns false or be enabled if CanExecute returns true.

WPF defines a bunch of commands already, so you don’t have to implement ICommand objects for Cut, Copy, and Paste and worry about where to store them. WPF’s built-in commands are exposed as static properties of five different classes:

  • ApplicationCommands—Close, Copy, Cut, Delete, Find, Help, New, Open, Paste, Print, PrintPreview, Properties, Redo, Replace, Save, SaveAs, SelectAll, Stop, Undo, and more
  • ComponentCommands—MoveDown, MoveLeft, MoveRight, MoveUp, ScrollByLine, ScrollPageDown, ScrollPageLeft, ScrollPageRight, ScrollPageUp, SelectToEnd, SelectToHome, SelectToPageDown, SelectToPageUp, and more
  • MediaCommands—ChannelDown, ChannelUp, DecreaseVolume, FastForward, IncreaseVolume, MuteVolume, NextTrack, Pause, Play, PreviousTrack, Record, Rewind, Select, Stop, and more
  • NavigationCommands—BrowseBack, BrowseForward, BrowseHome, BrowseStop, Favorites, FirstPage, GoToPage, LastPage, NextPage, PreviousPage, Refresh, Search, Zoom, and more
  • EditingCommands—AlignCenter, AlignJustify, AlignLeft, AlignRight, CorrectSpellingError, DecreaseFontSize, DecreaseIndentation, EnterLineBreak, EnterParagraphBreak, IgnoreSpellingError, IncreaseFontSize, IncreaseIndentation, MoveDownByLine, MoveDownByPage, MoveDownByParagraph, MoveLeftByCharacter, MoveLeftByWord, MoveRightByCharacter, MoveRightByWord, and more

Each of these properties does not return a unique type implementing ICommand. Instead, they are all instances of RoutedUICommand, a class that not only implements ICommand, but supports bubbling just like a routed event.

image

Lets develop a dialog that has a “Help” button, when clicked will open the help webpage. Let’s demonstrate how these built-in commands work by attaching some logic with the Help command defined in ApplicationCommands. Assuming the Button is named helpButton, you can associate it with the Help command in C# as follows:

helpButton.Command = ApplicationCommands.Help;

All RoutedUICommand objects define a Text property containing a name for the command that’s appropriate to show in a user interface. (This property is the only difference between RoutedUICommand and its base RoutedCommand class.) For example, the Help command’s Text property is (unsurprisingly) set to the string Help. The hard-coded Content on this Button could therefore be replaced as follows:

helpButton.Content = ApplicationCommands.Help.Text;

If you were to run the dialog with this change, you would see that the Button is now permanently disabled. That’s because the built-in commands can’t possibly know when they should be enabled or disabled, or even what action to take when they are executed. They delegate this logic to consumers of the commands. To plug in custom logic, you need to add a CommandBinding to the element that will execute the command or any parent element (thanks to the bubbling behavior of routed commands). All classes deriving from UIElement (and ContentElement) contain a CommandBindings collection that can hold one or more CommandBinding objects. Therefore, you can add a CommandBinding for Help to the dialog’s root Window as follows in

<Window.CommandBindings>
        <CommandBinding Command="Help"
                        CanExecute="CommandBinding_CanExecute"
                        Executed="CommandBinding_Executed" />
    </Window.CommandBindings>

 

Or in its code-behind file:

this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Help,
        CommandBinding_Executed, CommandBinding_CanExecute));

The methods called CommandBinding_Executed and CommandBinding_CanExecute have to be defined in code behind file as follows. These methods will be called back at appropriate times in order to plug in an implementation for the Help command’s CanExecute and Execute methods.

private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    if (firstName.Text == "help")
        e.CanExecute = true;
    else
        e.CanExecute = false;

}

private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
    System.Diagnostics.Process.Start("https://kishore1021.wordpress.com/&quot;);

}

 

In the XAML file, assign the command to the help button as follows.

<Button Grid.Row="3" Grid.Column="1" Command="Help"
          Name="MyHelpButton" Margin="4,190,0,5">
            Help
        </Button>

 

Compile the project and run the application. Initially, the help button is disabled. Enter help in the first name textbox and you can see that the help button is enabled. Now to take advantage of command binding, say you want to bring up help when user presses keyboard shortcut F2 key. We can bind our own input gestures to a command by adding KeyBinding and/or MouseBinding objects to the relevant element’s InputBindings collection in code as follows

this.InputBindings.Add(
              new KeyBinding(ApplicationCommands.Help, new KeyGesture(Key.F2)));

The same binding can be performed in XAML as follows

<Window.InputBindings>
    <KeyBinding Command="Help" Key="F2"/>
    <KeyBinding Command="NotACommand" Key="F1"/>
</Window.InputBindings>

 

The complete XAML code is

<Window x:Class="CommandBinding101.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="MainWindow" Height="350" Width="525">
    <Window.CommandBindings>
        <CommandBinding Command="Help"
                        CanExecute="CommandBinding_CanExecute"
                        Executed="CommandBinding_Executed" />
    </Window.CommandBindings>
    <Window.InputBindings>
        <KeyBinding Command="Help" Key="F2"/>
        <KeyBinding Command="NotACommand" Key="F1"/>
    </Window.InputBindings>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label>
            Enter your first name:
        </Label>
        <TextBox Grid.Row="0" Grid.Column="1"
           Name="firstName" Margin="0,5,10,5"/>

        <Label Grid.Row="1" >
            Enter your last name:
        </Label>
        <TextBox Grid.Row="1" Grid.Column="1"
           Name="lastName" Margin="0,5,10,5"/>

        <Button Grid.Row="2" Grid.Column="0"
          Name="Clear" Margin="2" Click="Clear_Click">
            Clear Name
        </Button>

        <Button Content="Enable Help" Margin="2" Name="button1" Grid.Column="1" Grid.Row="2" Click="button1_Click" />
        
        <Button Grid.Row="3" Grid.Column="1" Command="Help"
          Name="MyHelpButton" Margin="4,190,0,5">
            Help
        </Button>
        <Label Content="Type help in the first name edit box to enable the Help button" Margin="-1,13,12,164" Grid.Row="3" Grid.ColumnSpan="2" />
    </Grid>
    
</Window>

The complete code behind is

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CommandBinding101
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //MyHelpButton.Command = ApplicationCommands.Help;

           // this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Help,
           //  CommandBinding_Executed, CommandBinding_CanExecute));

            //this.InputBindings.Add(
            //  new KeyBinding(ApplicationCommands.Help, new KeyGesture(Key.F2)));

        }

        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (firstName.Text == "help")
                e.CanExecute = true;
            else
                e.CanExecute = false;

        }

        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://kishore1021.wordpress.com/&quot;);

        }

        private void Clear_Click(object sender, RoutedEventArgs e)
        {
            firstName.Clear();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            firstName.Text = "help";
        }
    }
}

If you use one of the preexisting RoutedUICommand objects for a WPF command, e.g. ApplicationCommands.Open, you’ll notice that the RoutedUICommand instance has a Text property.  This property in the command is used to set the label appearing on any MenuItem instances that have attached to the command by setting their Command property.  You don’t need to set the menu item’s Header property explicitly.

Download the source code here

If you really want the key to success, start by doing the opposite of what everyone else is doing.

Introduction to Templates–DataTemplate

Download the source code from here.

Most controls have some type of content, and that content often comes from data that you are binding to. In this sample, the data is the name and id of the student. In WPF, you use a DataTemplate to define the visual representation of data. Basically, what you put into a DataTemplate determines what the data looks like in the rendered application. For student name and id to be displayed  and highlighted, you create a DataTemplate as a resource:

            <DataTemplate DataType="{x:Type localXAMLClass:student}" >
                <Border BorderBrush="AliceBlue" BorderThickness="2">
                    <Grid Margin="10">
                        <TextBlock>
                            <Run Text="The Name of the student is "> </Run>
                            <TextBlock Background="LightBlue" Text="{Binding name}"></TextBlock>
                            <Run Text=" And his ID is "></Run>
                            <TextBlock Background="LightBlue" Text="{Binding id}" ></TextBlock>
                        </TextBlock>
                    </Grid>
                </Border>
            </DataTemplate>

Notice that the DataType property is very similar to the TargetType property of the Style. If your DataTemplate is in the resources section, when you specify the DataType property to a type and not assign it an x:Key, the DataTemplate is applied whenever that type appears. You always have the option to assign the DataTemplate with an x:Key and then set it as a StaticResource for properties that take DataTemplate types, such as the ItemTemplate property or the ContentTemplate property.

Before we dive into the data template used in the WPF application let’s see how a simple example works. First take a look at a simple class which represents a student:

namespace IntroductiontoTemplates1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public class student
    {
        private string Name;
        private int Id;

        public string name
        {
            get{return Name;}
            set{Name = value;}
        }

        public int id
        {
            get { return Id;}
            set { Id = value; }
        }
    }
}

 

The student class contains two properties name and id. If we were to display an instance of this class in a ContentControl, the XAML would be something like this:

  1. <Window x:Class="IntroductiontoTemplates1.MainWindow"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.         Title="MainWindow" Height="350" Width="525"
  5.         xmlns:localXAMLClass="clr-namespace:IntroductiontoTemplates1" >
  6.     <Grid>
  7.         <Grid.Resources>
  8.             <localXAMLClass:student x:Key="studentXAMLObject" name="kishore1021" id="1"></localXAMLClass:student>
  9.         </Grid.Resources>
  10.         <ContentControl
  11.             Content="{StaticResource studentXAMLObject}" >
  12.         </ContentControl>
  13.     </Grid>
  14. </Window>

 

The UI created by that XAML looks like the following:

image

That certainly isn’t too impressive. What you see above is what gets displayed as a result of calling ToString() on the student object referenced by the ContentControl. Let’s take a moment to examine what is going on here.

The example above creates an instance of the student class, which represents the student kishore1021. It also creates a ContentControl which is told to display that student object somehow. The ContentControl examines the student object and tries to figure out how to render it, but since student does not derive from UIElement it has no way of knowing how to do so. Once ContentControl is devoid of options, it ends up calling ToString() on the student object and then displays that text.

Override the inherited member Object.ToString() implementation.

        public override string ToString()
        {
            return "Returned from ToString() of student class";
        }

 

image

Now that we’ve seen how boring a student object looks in the absence of data templates, it’s time to add one into the mix. Here’s the same XAML used before, only this time there is a template for the student class:

            <DataTemplate DataType="{x:Type localXAMLClass:student}" >
                <Border BorderBrush="AliceBlue" BorderThickness="2">
                    <Grid Margin="10">
                        <TextBlock>
                            <Run Text="The Name of the student is "> </Run>
                            <TextBlock Background="LightBlue" Text="{Binding name}"></TextBlock>
                            <Run Text=" And his ID is "></Run>
                            <TextBlock Background="LightBlue" Text="{Binding id}" ></TextBlock>
                        </TextBlock>
                    </Grid>
                </Border>
            </DataTemplate>

 

Essentially, the DataTemplate in the above example defines that whenever there is a student class object, it should appear as the text “The name of the student is <xyz> And his ID is <322323>. With this DataTemplate, our application now looks like this:

 

image

That is how the XAML renders to show the proper data content: The student object is displayed much more intelligently when a data template is applied. The information held within it is now displayed as part of a sentence, and that sentence is wrapped in a curved blue border. Keep in mind that the rendition of a student object seen above is completely arbitrary. It can be displayed in whatever way is considered appropriate for the application in which it exists.

The complete code of the .cs file is as follows

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace IntroductiontoTemplates1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public class student
    {
        private string Name;
        private int Id;

        public string name
        {
            get{return Name;}
            set{Name = value;}
        }

        public int id
        {
            get { return Id;}
            set { Id = value; }
        }

        public override string ToString()
        {
            return "Returned from ToString() of student class";
        }

    }

}

The complete XAML code is as follows

<Window x:Class="IntroductiontoTemplates1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="MainWindow" Height="350" Width="525"
        xmlns:localXAMLClass="clr-namespace:IntroductiontoTemplates1" >
    <Grid>
        <Grid.Resources>
            <DataTemplate DataType="{x:Type localXAMLClass:student}" >
                <Border BorderBrush="Red" BorderThickness="2">
                    <Grid Margin="10">
                        <TextBlock>
                            <Run Text="The Name of the student is "> </Run>
                            <TextBlock Background="LightBlue" Text="{Binding name}"></TextBlock>
                            <Run Text=" And his ID is "></Run>
                            <TextBlock Background="LightBlue" Text="{Binding id}" ></TextBlock>
                        </TextBlock>
                    </Grid>
                </Border>
            </DataTemplate>

            <localXAMLClass:student x:Key="studentXAMLObject" name="kishore1021" id="1"></localXAMLClass:student>
        </Grid.Resources>
        
        <ContentControl
            Content="{StaticResource studentXAMLObject}" >
        </ContentControl>
    </Grid>
</Window>

 

Download the source code from here.

 

All men dream but not equally. Those who dream by night in the dusty recesses of their minds wake in the day to find that it was vanity; but the dreamers of the day are dangerous men, for they may act their dream with open eyes to make it possible. – T.E. Lawrence

Introduction to Multi Binding and Multi value converter using IMultiValueConverter & MultiBinding

For Introduction to Value Converters, see the post here.

For more information on mode property, see the the post on mode here.

MultiBinding allows us to bind a binding target property to a list of source properties and then apply logic to produce a value with the given inputs. This example demonstrates how to use MultiBinding. The following example produces a TextBox that adds the numbers in TextBox1 and TextBox2 and puts the result into TextBox3. Here we have two source properties and the one target property. When you enter numbers in the TextBox1 and TextBox2 , the converter comes into play and automatically adds them and puts the result into TextBox3. The values of the Mode and UpdateSourceTrigger properties determine the functionality of the MultiBinding and are used as the default values for all the bindings in the collection unless an individual binding overrides these properties. For example, if the Mode property on the MultiBinding object is set to TwoWay, then all the bindings in the collection are considered TwoWay unless you set a different Mode value on one of the bindings explicitly.

In the following code, AddConverter implements the IMultiValueConverter interface. AddConverter takes the values from the individual bindings and stores them in the values object array. The order in which the Binding elements appear under the MultiBinding element is the order in which those values are stored in the array.

 

Figure1: Important Classes hierarchy.

Figure2: Binding classes hierarchy

The XAML for the above mentioned logic is as follows.

<Window x:Class="DataConversion.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="MainWindow" Height="350" Width="525"
        xmlns:mylocalXAMLnamespace="clr-namespace:DataConversion">
    <StackPanel>
        <StackPanel.Resources>
            <mylocalXAMLnamespace:AddConverter x:Key="XAMLResourceAddConverter" />
        </StackPanel.Resources>

        <TextBox Name="TextBox1" Text="10"></TextBox>
        <TextBox Name="TextBox2" Text="20"></TextBox>
        <Label Content="Sum of above two values:"></Label>
        <TextBox Name="textBox3">
            <TextBox.Text>
                <MultiBinding Converter="{StaticResource XAMLResourceAddConverter}">
                    <Binding ElementName="TextBox1" Path="Text"/>
                    <Binding ElementName="TextBox2" Path="Text"/>
                </MultiBinding>
            </TextBox.Text>
        </TextBox>
    </StackPanel>
</Window>

 

The MultiBinding tag takes binding as a parameter. See the following C# code that does the binding.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Markup;

namespace DataConversion
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

    }

    public class AddConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            int result = Int32.Parse((string)values[0]) + Int32.Parse((string)values[1]);
            return result.ToString();
        }
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException("Cannot convert back");
        }
    }

}

 

You can specify multiple bindings in a MultiBinding object. When you use the MultiBinding object with a converter, it produces a final value for the binding target based on the values of those bindings. For example, color might be computed from red, blue, and green values, which can be values from the same or different binding source objects. When a value moves from the target to the sources, the target property value is translated to a set of values that are fed back into the bindings.

Download the Source Code from here

If it’s a good idea, go ahead and do it. It is much easier to apologize than it is to get permission. Admiral Grace Hopper

IValueConverter with Markup Extension

We have seen the Introduction to Value Converters in the previous post.  Converter is a Binding property of type IValueConverter. You can set this property to an instance of a class which implements that interface to intercept any movement of data from the binding source to the binding target, or vice versa. Value converters are very convenient and are used quite often.  If you want to use a normal ValueConverter in XAML, you have to add an instance of it to the resources and reference it by using a key. To learn more about instantiating an object as a resource in XAML, see the post. This is cumbersome, because and the key is typically just the name of the converter or you can derive your value converter from MarkupExtension and return its own instance in the ProvideValue override. So you can use it directly without referencing it from the resources.

public override object ProvideValue(IServiceProvider serviceProvider)
{
    throw new NotImplementedException();
}

So to enhance our experience with converters,  derive value converters from MarkupExtension. This way you can create and use it in the binding like this: Text={Binding studentname, Converter={x:MyConverter}}

Following are the steps to create a converter with Markup extension.

  1. Import namespace
    using System.Windows.Markup;

  2. Derive our class from MarkupExtension, IValueConverter
    public class ScoreToColorConverter : MarkupExtension, IValueConverter

  3. Override the ProvideValue method of MarkupExtension class and return this
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

  4. Implement the IValueConverter interface methods Convert & ConvertBack
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string s = (string) value;
        if (Int32.Parse(s) <= 35)
            return new SolidColorBrush(Colors.Red);
        else
            return new SolidColorBrush(Colors.Green);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

  5. Specify the xmlns:XXXX in the Window XAML tag
    xmlns:MyXAMLClass="clr-namespace:DataBinding_MultiConverter2"

  6. Specify the UI elements and mention the binding properties. Notice here that we are specifying the Binding converter property as Converter={MyXAMLClass:ScoreToColorConverter}, which is a simple and decent implementation.
    <TextBox Grid.Row="0" Name="TB1" Text="90"></TextBox>
     <TextBox Grid.Row="1" Name="TB2" Background="{Binding ElementName=TB1, Path=Text, Converter={MyXAMLClass:ScoreToColorConverter}}"></TextBox>

The complete XAML is:

<Window x:Class="DataBinding_MultiConverter2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="MainWindow" Height="350" Width="525"
        xmlns:MyXAMLClass="clr-namespace:DataBinding_MultiConverter2"
        >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Name="TB1" Text="90"></TextBox>
        <TextBox Grid.Row="1" Name="TB2" Background="{Binding ElementName=TB1, Path=Text, Converter={MyXAMLClass:ScoreToColorConverter}}"></TextBox>
    </Grid>
</Window>

The complete source code of the classes used is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Markup;

namespace DataBinding_MultiConverter2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public class ScoreToColorConverter : MarkupExtension, IValueConverter
    {

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string s = (string) value;
            if (Int32.Parse(s) <= 35)
                return new SolidColorBrush(Colors.Red);
            else
                return new SolidColorBrush(Colors.Green);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Download the Source code from here. Default conversions may be available because of type converters that are present in the type being bound to. This behavior will depend on which type converters are available in the target. If in doubt, create your own converter.

Following are some typical scenarios where it makes sense to implement a data converter:

  • Your data should be displayed differently, depending on culture. For instance, you might want to implement a currency converter or a calendar date/time converter based on the values or standards used in a particular culture.

  • The data being used is not necessarily intended to change the text value of a property, but is instead intended to change some other value, such as the source for an image, or the color or style of the display text. Converters can be used in this instance by converting the binding of a property that might not seem to be appropriate, such as binding a text field to the Background property of a table cell.

  • More than one control or to multiple properties of controls are bound to the same data. In this case, the primary binding might just display the text, whereas other bindings handle specific display issues but still use the same binding as source information.

  • In the case of a MultiBinding, where a target property has a collection of bindings, you use a custom IMultiValueConverter to produce a final value from the values of the bindings. For example, color may be computed from red, blue, and green values, which can be values from the same or different binding source objects.

See Introduction to Value Converters in the previous post

Download the Source code from here

In organizations, real power and energy is generated through relationships. The patterns of relationships and the capacities to form them are more important than tasks, functions, roles, and positions. –Margaret Wheatley