Understanding Content Controls in WPF

Discussion in 'C#' started by shabbir, May 17, 2014.

  1. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    WPF content controls are a specialized form of WPF controls and are used to store content either entered by the user or read from any other data source. Content controls can contain only one child element. This is unlike layout controls such as Grid, WrapPanel and StackPanel controls that contain multiple child elements. (Layout controls have been explained in this tutorial).

    In this article, a detailed overview of WPF content controls has been given with the help of small code examples. If you are absolute beginner to WPF layouts and application syntax, I would suggest you to read this tutorial to understand the basics and then you can come back and continue with this article.

    What Are Content Controls?



    All the Layout controls derive themselves from the abstract class Panel. The Panel class contains the ability to hold multiple controls such as Grid layout contains multiple controls. On the other hand, all the content controls derive from an abstract base class ContentControl which can only hold one element. Window control is a content control. To hold multiple elements in Window controls, a layout control holding multiple elements is placed inside a Window control.

    Typical content controls include ToolTip control, Label control all types of Button control, ScrollViewer control and custom UserControl. Another set of content control classes derive from HeaderedContentControl class which derives from the abstract ContentControl class. These controls contain a header region and content region. Typical examples of these controls are TabItem, GroupBox and Expander controls.

    Content Property

    In case of Layouts that derive from Panel class all the elements in a layout were stored in the form of collections. In case of content control, the Content property of the control is set to the type of content contained by the control. If a content control class doesn’t derive from UIElement type, the ToString method is called on the element to get the string content that will be stored in the Content property. In case of UIElement type content, the OnRender method is called and the returned object is stored in the Content property of the content control.

    Aligning Content

    All the controls contain HorizontalAlignment and VerticalAlignment properties that are used to align the controls horizontally or vertically inside a layout, respectively. However, these properties do not set the content alignment of the controls. To set the alignment the alignment of the content inside a control, the HorizontalContentAlignment and the VerticalContentAlignment properties are used. Another important property of the content controls is that of Padding which adds space from the edge of the content control to the content that it contains. In the first example of this tutorial, these three properties have been demonstrated in action.

    Example1
    Code:
    <Window x:Class="WPFTutorial.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="200" Width="400" MinWidth="150">
        <StackPanel Orientation="Vertical">
            <Button HorizontalContentAlignment="Center" Padding="10">Button1</Button>
            <Button HorizontalContentAlignment="Left">Button2</Button>
            <Button VerticalContentAlignment="Stretch">Button3</Button>
        </StackPanel>
    </Window>
    
    In Example1, there is a StackPanel inside the main Window element. This StackPanel contains three Button content controls. The content type of the controls is string. The HorizontalContentAlignment property of Button1 is set to Center and a padding of 10 device independent points have been added on all sides of the first button.

    The HorizontalContentAlignment of the second button is set to Left which would align the string content Button2 to the left. Another important thing to note here is that since no padding is added to the Button2, therefore there would be no space between the sides and the content.

    Finally, the VerticalContentAlignment of the third button is set to Stretch which would stretch the content vertically. The output of the code in Example1 has been shown in the following picture.

    Output1

    [​IMG]

    Drawing Shapes in Content Controls



    Content controls are more than just containing simple text content. For instance an image can also serve as the content of a content control element. Apart from images, shapes can also be drawn and added to a content control. In the following example, a Button type content control has been added in Window element and three polygons have been drawn inside the Button. The Polygon class from the System.Windows.Shapes namespace has been used for this purpose. Have a look at the code in example2.

    Example2
    Code:
    <Window x:Class="WPFTutorial.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="200" Width="400" MinWidth="150">
        <Button Margin="10">
            <Grid>
            <Polygon Points="200, 50 80,8 100, 40" 
                     Fill="Azure"/>
            <Polygon Points="2, 80 100, 20 200, 100" 
                     Fill="Bisque"/>
            </Grid>
        </Button>
    </Window>
    
    Here in the above code a Button control has been added in top level Window content control. Remember that inside any content control, only one element can be added. Therefore, to add multiple elements inside content control, a layout control is used. Therefore, to add two polygonal shapes content to the Button control, a Grid layout has been declared and two Polygons with different shapes have been added to this Button. The output of the code in Example2 is as follows:

    Output2:

    [​IMG]

    Label Content Controls



    Of all the WPF content controls, Label content control is simplest of all. Like the Button control, Label control can accept a variety of content types ranging from simple strings to more complex UIElement contents.

    However, the most astonishing feature of label control is its support for mnemonics. Mnemonics in Label controls are essentially a shortcut key, which when pressed sets the focus of the application to the control to which it links or refers.

    To shift focus to the other control upon being pressed, the Label uses a Target property whose Binding ElementName attribute is set to the control name to which focus has to be shifted. The third example of this tutorial demonstrates the concept of mnemonics in WPF labels. Have a look at the XAML code.

    Example3
    Code:
    <Window x:Class="WPFTutorial.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="200" Width="400" MinWidth="150">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
        <Label Grid.Row="0" Target="{Binding ElementName= TextBoxA}">Choose TextBox _A</Label>
            <TextBox Name="TextBoxA" Grid.Row="1"></TextBox>
        <Label Grid.Row="2" Target="{Binding ElementName= TextBoxB}">Choose TextBox _B</Label>
            <TextBox Name="TextBoxB" Grid.Row="3"></TextBox>
        </Grid>
    </Window>
    
    Closely watch the code in the above example. Lots of things are happening. First of all, a Grid layout has been added to the top level Window element. This Grid contains four rows and one column by default since no Grid.Column definition attached property has been added to the Grid.

    In the first row of the Grid, a label has been added. Let us revisit the definition of the label control in the above example to see how mnemonics are used with labels:
    Code:
    <Label Grid.Row="0" Target="{Binding ElementName= TextBoxA}">Choose TextBox _A</Label>
    
    The above line tells that a label has been placed in the 0th row of the Grid and its Target property has an attribute Binding that binds the short key and ElementName is the attribute to which the Key would link to. Here in this case, the Label key would shift the focus to the control named TextBoxA.

    A question here arises that, how the shortcut key is specified? The answer is that it is specified in the string content of the Label by placing an underscore before the letter that we want to nominate as the shortcut key. For instance in the above mentioned label definition the content is “Choose TextBox _A” here the underscore is prefixed before the letter A, hence the shortcut key for changing focus to TextBoxA, Key A can be used.

    In the next line of code, a TextBox control named TextBoxA has been added to which the aforementioned label would point. Similarly, another label has been added that links to TextBoxB through shortcut key B. Finally the actial TextBoxB control has been added. The output of the code in Example3 is as follows:

    Output3

    [​IMG]

    Now when the above window appears, if Alt + B keys are pressed, the focus shifts to TextBoxB control. Similarl, if Alt + A key is pressed, focus shifts to TextBoxA. Also, pressing Alt alone would highlight all the shortcut keys on window.

    Using Button Controls



    There are three types of WPF button content controls. These are simple Button, CheckBox button and the RadioButton. In the following section the first two types of WPF button i.e. the Simple Button and the CheckBox button controls have been explained, while the RadioButton control is left for the readers to explore themselves.

    The Simple Button Control

    The simple button control behaves in a similar to the traditional windows form based button that when clicked used to trigger some event. In WPF, the simple Button control has got two more added functionalities that are worth mentioning here.
    • IsDefault - If the IsDefault property of any button control is set to true, that button is triggered whenever the enter key is pressed.
    • IsCancel - If the IsCancel property of any button control is set to true, that button is triggered whenever escape key is pressed on the keyboard.
    The next example of this tutorial, demonstrates this concept where two buttons have their IsCancel and IsDefault property set to true. Have a look at the code in Example4.

    Example4
    Code:
    <Window x:Class="WPFTutorial.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="200" Width="400" MinWidth="150">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <Button Name="ButtonCancel" Grid.Row="0" IsCancel="True" Click="ButtonCancelClicked" >Close Button</Button>
            <TextBlock Name="TextBox1" Grid.Row="1"></TextBlock>
            <Button Name="ButtonEnter" Grid.Row="2" IsDefault="True" Click="ButtonEnterClicked">Enter Button</Button>
            <TextBlock Grid.Row="4" Name="TextBox2"></TextBlock>
        </Grid>
    </Window>
    
    In the above example, again there is a Grid control that contains four rows. In the first row a Button control, named ButtonCancel has been defined. The IsCancel property of this button has been set to true which means that when Escape key is pressed from the keyboard, the click event of this button would execute. In the second row, a TextBox Named TextBox1 has been added.

    In the third row of the grid, another Button control, named ButtonEnter has been defined, this button contains content string “Enter Button”. When Enter key is pressed from the keyboard, the click even associated with this ButtonEnter would execute. The code behind MainWindow.xaml.cs will contain the event handling code for the two buttons and should look like this:
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    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 WPFTutorial
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
            }
            private void ButtonCancelClicked(object sender, RoutedEventArgs e)
            {
                TextBox1.Text = "Cancel Button Clicked";
            }
            private void ButtonEnterClicked(object sender, RoutedEventArgs e)
            {
                TextBox2.Text = "Enter Button Clicked";
            }
        }
    }
    
    The event handling code says that when ButtonCancelClicked event is executed by pressing the Escape key on keyboard, the Text property of the TextBox1 should display “Cancel Button Clicked”. Similarly, when ButtonEnterClicked event is executed by pressing the Escape key on keyboard, the Text property of the TextBox2 should display “Enter Button Clicked”. The output of the code in Example4 is as follows:

    Output4

    [​IMG]

    The WPF CheckBox Button Control



    The CheckBox button control is another type of Button control that provides check and uncheck feature. The IsChecked property of the CheckBox control can be set to true, false and {x:Null}. If the IsChecked property is set to true, the CheckBox appears checked, if the IsChecked property is set to false, the CheckBox appears unchecked. The {x:Null} refers to the indeterminate state In which case the CheckBox appears blue or grey, unchecked. The 5th example of this tutorial demonstrates this concept. Have a look at it.

    Example5
    Code:
    <Window x:Class="WPFTutorial.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="200" Width="400" MinWidth="150">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <CheckBox Grid.Row="0" IsChecked="True">Is checked</CheckBox>
            <CheckBox Grid.Row="1" IsChecked="False">Is checked</CheckBox>
            <CheckBox Grid.Row="2" IsChecked="{x:Null}">Is checked</CheckBox>
        </Grid>
    </Window>
    
    In the above example, there are three CheckBox controls that have been added to the first three rows of the Grid control, respectively. The IsChecked property of the first CheckBox is set to true. For the second CheckBox it is set to false and finally for the third CheckBox this property has been set to {x:Null} which means it is indeterminate. The output of the code in Example5 as follows:

    Output5

    [​IMG]

    WPF content controls are extremely important to comprehend, since the content constitutes the most important aspect of a WPF application. I would suggest you to further explore the Content Controls in WPF. In case of any confusion, leave a comment and I will get back a.s.a.p. For now, Happy coding to all.
     
    Last edited: Jan 21, 2017

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice