Windows Presentation Foundation

Hello, WPF

WPF from Scratch
Navigation Applications
Content Model
Layout
Controls
Data Binding
Dependency Properties
Resources
Styles and Control Templates
Graphics
Application Deployment
Where Are We?

Layout

Introduction
Layout Basics
DockPanel
StackPanel
Grid
Canvas
Viewbox
Text Layout
Common Layout Properties
When Content Doesn't Fit
Custom Layout
Where Are We?

Controls

Introduction
What Are Controls?
Handling Input
Built-In Controls
Where Are We?

Data Binding

Introduction
Without Data Binding
Data Binding
Binding to List Data
Data Sources
Master-Detail Binding
Where Are We?

Styles and Control Templates

Introduction
Without Styles
Inline Styles
Named Styles
Element-Typed Styles
Data Templates and Styles
Triggers
Control Templates
Where Are We?

Resources

Introduction
Creating and Using Resources
Resources and Styles
Binary Resources
Global Applications
Where Are We?

Graphics

Introduction
Graphics Fundamentals
Shapes
Brushes and Pens
Transformations
Visual-Layer Programming
Video and 3-D
Where Are We?

Animation

Animation Fundamentals
Timelines
Storyboards
Key Frame Animations
Creating Animations Procedurally
Where Are We?

Custom Controls

Introduction
Custom Control Basics
Choosing a Base Class
Custom Functionality
Templates
Default Visuals
Where Are We?

ClickOnce Deployment

A Brief History of Windows Deployment
ClickOnce: Local Install
The Pieces of ClickOnce
Publish Properties
Deploying Updates
ClickOnce: Express Applications
Choosing Local Install versus Express
Signing ClickOnce Applications
Programming for ClickOnce
Security Considerations
Where Are We?

Control Templates

5.7. Control Templates

If we take a closer look at our current tic-tac-toe game, we'll see that the Button objects aren't quite doing the job for us. What tic-tac-toe board has rounded inset corners (Figure 5-14)?

What we really want here is to be able to keep the behavior of the buttoni.e., holding content and firing click eventsbut we want to take over the look of the

Figure 5-14. Tic-tac-toe boards don't have rounded insets!


button. WPF allows this kind of thing because the intrinsic controls are built to be looklessi.e., they provide behavior, but the look can be swapped out completely by the client of the control.

Remember how we used data templates to provide the look of a non-visual object? We can do the same to a control using a control template, which is a set of storyboards, triggers, and, most importantly, elements that provide the look of a control.

To fix our buttons' looks, we'll build ourselves a control-template resource. Let's start things off in Example 5-31 with a simple rectangle and worry about showing the actual button content later.

Example 5-31. A minimal control template
<Window.Resources>
  <ControlTemplate x:Key="ButtonTemplate">

    <Rectangle />
  </ControlTemplate>
  ...
  <!-- let's just try one button for now... -->
  <Button Template="{StaticResource ButtonTemplate}" ... />
  ...

</Window.Resources>

Figure 5-15 shows the results of setting a single button's Template property.

Notice that no vestiges of what the button used to look like remain in Figure 5-15. Unfortunately, no vestige of our rectangles can be seen, either. The problem is that, without a fill explicitly set, the rectangle's fill defaults to transparent, showing the grid's black background. Let's set it to our other favorite Halloween color instead:

    <ControlTemplate x:Key="ButtonTemplate">

      <Rectangle Fill="Orange" />
    </ControlTemplate>

Figure 5-15. Replacing the control template with something less visual than we'd like...


Now we're getting somewhere, as Figure 5-16 shows.

Figure 5-16. Replacing the button's control template with an orange rectangle (Color Plate 11)


Notice how square the corners are? Also, if you click, you won't get the depression that normally happens with a button (and I don't mean "a sad feeling").

5.7.1. Control Templates and Styles

Now that we're making some progress on the control template, let's replicate it to the other buttons. We can do so by setting each button's Template property by hand or, as is most common, we can bundle the control template with the button's style, as in Example 5-32.

Example 5-32. Putting a control template into a style
<Window.Resources>
  <Style TargetType="{x:Type Button}">
    ...
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate>

          <Rectangle Fill="Orange" />
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
  ...

</Window.Resources>
...
<!-- No need to set the Template property for each button -->
<Button ... x:Name="cell00" />
...

As Example 5-32 shows, the Template property is the same as any other and can be set with a style. Figure 5-17 shows the results.

Figure 5-17. Spreading the orange (Color Plate 12)


Still, the orange is kind of jarring, especially since the settings on the style call for a white background. We can solve this problem with template bindings.

5.7.2. Template Binding

To get back to our white buttons, we could hardcode the rectangle's fill to be white, but what happens when a style wants to change it (such as in the animation we've now broken)? Instead of hardcoding the fill of the rectangle, we can reach out of the template into the properties of the control using template binding, as in Example 5-33.

Example 5-33. Template binding to the Background property
<Style TargetType="{x:Type Button}">
  <Setter Property="Background" Value="White" />
  ...
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate x:Key="ButtonTemplate">

        <Rectangle Fill="{TemplateBinding Property=Background}" />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  ...

</Style>

A template binding is like a data binding, except that the properties to bind come from the control whose template you're replacing (called the templated parent ). In our case, things like Background, HorizontalContentAlignment, and so on, are fair game for template binding from the parent. And, like data binding, template bindings are smart enough to keep the properties of the items inside the template up to date with changing properties on the outside, as set by styles, animations, etc. For example, Figure 5-18 shows the effect of aliasing the rectangle's Fill property to the button's Background property with our click animation and mouse-over behavior still in place.

Figure 5-18. Setting the rectangle's fill using property aliasing (Color Plate 13)


We're not quite through yet, however. If we're going to change the paint swatch that Figure 5-18 has become into a playable game, we have to show the moves. To do so, we'll need a content presenter.

5.7.3. Content Presenters

If you've ever driven by a billboard or a bench at a bus stop that says "Your advertisement here!" then that's all you need to know to understand content presenters. A content presenter is the WPF equivalent of "your content here" that allows content held by a ContentContainer control to be plugged in at runtime.

In our case, the content is the visualization of our PlayerMove object. Instead of reproducing all of that work inside of the button's new control template, we'd just like to drop it in at the right spot. The job of the content presenter is to take the content provided by the templated parent and do all of the things necessary to get it to show up properly, including styles, triggers, etc. The content presenter itself can be dropped into your template wherever you'd like to see it (including multiple times, if it tickles your fancye.g., to produce a drop shadow). In our case, we'll compose a content presenter in Example 5-34 with the rectangle inside a grid using techniques from Chapter 2.

Example 5-34. A content presenter
<Style TargetType="{x:Type Button}">
  <Setter Property="Background" Value="White" />

  ...
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate>
        <Grid>
          <Rectangle Fill="{TemplateBinding Property=Background}" />
          <ContentPresenter
            Content="{TemplateBinding Property=ContentControl.Content}" />

        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  ...
</Style>

In Example 5-34, the content presenter's Content property is bound to the ContentControl.Content property so that content comes through. As with styles, we can avoid prefixing template binding property names with classes by setting the TargetType attribute on the ContentTemplate element:

    <ControlTemplate TargetType="{x:Type Button}">
      <Grid>
        <Rectangle Fill="{TemplateBinding Property=Background}" />
        <ContentPresenter
          Content="{TemplateBinding Property=Content}" />
      </Grid>

    </ControlTemplate>

Further, with the TargetType property in place, you can drop the explicit template binding on the Content property altogether, as it's now set automatically:

    <ControlTemplate TargetType="{x:Type Button}">

      <Grid>
        <Rectangle Fill="{TemplateBinding Property=Background}" />
        <!-- with TargetType set, the template binding for the -->
        <!-- Content property is no longer required -->
        <ContentPresenter />
      </Grid>

    </ControlTemplate>

The content presenter is all we need to get our game back to being functional, as shown in Figure 5-19.

Figure 5-19. Adding a content presenter to our control template (Color Plate 14)


5.7.4. The Real Work

The last little bit of work is getting the padding right. Since the content presenter doesn't have its own Padding property, we can't bind the Padding property directly (it doesn't have a Background property, either, which is why we used Rectangle and its Fill property). For properties that don't have a match on the content presenter, you have to find mappings or compose the elements that provide the functionality that you're looking for. For example, Padding is an amount of space inside of a control. Margin, on the other hand, is the amount of space around the outside of a control. Since they're both of the same type, System.Windows.Thickness, if we could map the Padding from the inside of our button to the outside of the content control, our game would look very nice:

    <Style TargetType="{x:Type Button}">
      <Setter Property="Background" Value="White" />
      <Setter Property="Padding" Value="10,5" />
      ...
      <Setter Property="Template">
        <Setter.Value>

          <ControlTemplate TargetType="{x:Type Button}">
            <Grid>
              <Rectangle Fill="{TemplateBinding Property=Background}" />
              <ContentPresenter
                Content="{TemplateBinding Property=Content}"
                Margin="{TemplateBinding Property=Padding}" />
            </Grid>
          </ControlTemplate>

        </Setter.Value>
      </Setter>
      ...
    </Style>

Figure 5-20 shows our completed tic-tac-toe variation.

Figure 5-20. Binding the Padding property to the Margin property (Color Plate 15)


Like the mapping between Padding and Margin, building up the elements that give you the look you want and binding the appropriate properties from the templated parent is going to be a lot of the work of creating your own control templates.


©2008 FAQ - WPF Labs - Discuss - Terms of Use - Privacy Policy - About WPF
- Interview Questions - Sharepoint Articles - Interview Questions Resource Library - All about LINQ - MS Knowledgebase Articles - Electronics and Hardware discussions