#837 – A Window Cannot Be a Child of a ContentControl

The content of a ContentControl can be just about anything, including either UI elements or simple CLR objects.  For example, the content of a CheckBox can be something more than a simple text string.

One of the few elements that cannot be used as content for a ContentControl is a Window.  It wouldn’t make sense to place a Window element as the content of something else, like a Button.  A Window can only be the topmost element of the logical tree.

If you do try to include a Window as a child of another element, you’ll get an exception at run-time, when the XAML is parsed.

    <Button Height="23" Width="80">
        <Window Title="A window in a button?" />
    </Button>

837-001

#836 – Setting a ContentControl’s Content to a CLR Object

You’ll typically set the Content property of a content control to an instance of an UIElement, which will typically include one or more controls.  (E.g. On a Button).

You can also set a Content property to a plain CLR object, i.e. an object that derives from System.Object.  When you do this, a content control will render the object by calling its ToString method.

In the example below, a Tooltip’s content is set to an instance of a Dog class.  When the tooltip is displayed, the dog’s ToString method is called.

<Window.Resources>
    <local:Dog x:Key="myDog" Name="Kirby" Age="15" FavToy="Tennis ball"/>
</Window.Resources>

<StackPanel DataContext="{StaticResource myDog}">
    <Label Content="{Binding Name}" Margin="10"
           ToolTip="{Binding}"/>
</StackPanel>

Assume that the ToString method dumps out the contents of the object:

        public override string ToString()
        {
            StringBuilder sbValue = new StringBuilder(string.Format("Dog {0}:\n", Name));
            sbValue.AppendFormat("  Age: {0}\n", Age);
            sbValue.AppendFormat("  Favorite Toy: {0}\n", FavToy);

            return sbValue.ToString();
        }

836-001

#833 – CheckBox is a ContentControl

CheckBox control derives from ContentControl, which means that it can contain a single piece of content.  In the case of a CheckBox, this content is rendered next to the actual check box that a user can check on or off.

You typically set the content of a CheckBox to a string, which gets rendered next to the check box.

        <CheckBox Content="Learn to juggle"/>
        <CheckBox Content="Read War and Peace"/>
        <CheckBox Content="Visit Japan"/>

833-001
You can, however, set the Content property to anything that you like, including a panel that contains other controls.

        <CheckBox VerticalContentAlignment="Center">
            <CheckBox.Content>
                <StackPanel>
                    <Image Source="Juggler.png" Height="85"/>
                    <Label Content="Learn to juggle"/>
                </StackPanel>
            </CheckBox.Content>
        </CheckBox>
        <CheckBox VerticalContentAlignment="Center">
            <CheckBox.Content>
                <StackPanel>
                    <Image Source="leo.jpg" Height="85"/>
                    <Label Content="Read War and Peace"/>
                </StackPanel>
            </CheckBox.Content>
        </CheckBox>
        <CheckBox VerticalContentAlignment="Center">
            <CheckBox.Content>
                <StackPanel>
                    <Image Source="kinkakuji.jpg" Height="85"/>
                    <Label Content="Visit Japan"/>
                </StackPanel>
            </CheckBox.Content>
        </CheckBox>

833-002

#361 – Creating a ToggleButton Whose Content Is an Image

Because ToggleButton is a ContentControl, it can contain a single child element that can be any .NET object.  You typically set the ToggleButton’s content to a text string, which appears as a label on the button.  But you can also set the content to some other control.

In the example below, the content of each ToggleButton in a panel is set to an Image control.

    <StackPanel HorizontalAlignment="Center" Margin="15">
        <Label Content="Click on cartoon characters that you like:"/>
        <StackPanel>
            <ToggleButton HorizontalAlignment="Center" Margin="5" Padding="5">
                <Image Source="001-Bugs.jpg" Stretch="None"/>
            </ToggleButton>
            <ToggleButton HorizontalAlignment="Center" Margin="5" Padding="5">
                <Image Source="002-Underdog.jpg" Stretch="None"/>
            </ToggleButton>
            <ToggleButton HorizontalAlignment="Center" Margin="5" Padding="5">
                <Image Source="003-Betty.jpg" Stretch="None"/>
            </ToggleButton>
            <ToggleButton HorizontalAlignment="Center" Margin="5" Padding="5">
                <Image Source="004-Bart.jpg" Stretch="None"/>
            </ToggleButton>
        </StackPanel>
    </StackPanel>

#357 – RadioButton is a ContentControl

Because the RadioButton control is a ContentControl, it can contain a single child element that can be any .NET object.  When you specify a value for the Content property in XAML, you specify a text string that is used as the radio button’s label.  But you can also set the content to some other control.

In the example below, we set each RadioButton‘s content to a StackPanel containing an Image and a Label.  The user can still select just one item at a time from the group.

        <StackPanel HorizontalAlignment="Center" Margin="15">
            <Label Content="Who is your favorite animated character?"/>
            <RadioButton>
                <StackPanel>
                    <Image Source="001-Bugs.jpg" Stretch="None"/>
                    <Label Content="Bugs Bunny"/>
                </StackPanel>
            </RadioButton>
            <RadioButton>
                <StackPanel>
                    <Image Source="002-Underdog.jpg" Stretch="None"/>
                    <Label Content="Underdog"/>
                </StackPanel>
            </RadioButton>
            <RadioButton>
                <StackPanel>
                    <Image Source="003-Betty.jpg" Stretch="None"/>
                    <Label Content="Betty Boop"/>
                </StackPanel>
            </RadioButton>
            <RadioButton>
                <StackPanel>
                    <Image Source="004-Bart.jpg" Stretch="None"/>
                    <Label Content="Bart Simpson"/>
                </StackPanel>
            </RadioButton>
        </StackPanel>

#341 – Create a Button with an Image and Text

Since a Button is a ContentControl, it can have any other control as its content, rather than text.  You can include an Image control, to create a button with an image on its face.  You can also include multiple controls on the button, by settings its main content to be a container, which in turn contains other controls.

In the example below, we create a Button that has both an image and some text (a caption).

        <Button HorizontalAlignment="Center" VerticalAlignment="Center"
                Margin="10" >
            <StackPanel>
                <Image Source="Misc-Settings-icon.png" Height="64" Width="64"/>
                <Label Content="Settings" HorizontalAlignment="Center"/>
            </StackPanel>
        </Button>

#340 – Create a Button with an Image

To create a Button that has an image on the surface of the button, rather than text, you use an Image control as the content of the button.

You need to tell the Image control where to find its image.  The easiest way to locate images is to just include them as resources in your project.

  • Embed the image as a binary resource in your project
  • Set the Build Action of the image to Resource
  • Use the filename as the image’s Source

In the example below, we’ve added the Misc-Settings-icon.png file to our project.

We can then create a Button that has this image as its main content.  Because Button is a ContentControl, it can contain another control as its content.

    <StackPanel>
        <Button HorizontalAlignment="Center" VerticalAlignment="Center"
                Margin="10" >
            <Image Source="Misc-Settings-icon.png" Height="64" Width="64"/>
        </Button>
        <Label Content="That's a button up there.." HorizontalAlignment="Center"/>
    </StackPanel>