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?

Data Templates and Styles

5.5. Data Templates and Styles

Let's imagine that we wanted to implement a version of tic-tac-toe that's more fun to play (that's an important feature in most games). For example, one variant of tic-tac-toe allows players to have only three of their pieces on at any one time, dropping the first move off when the fourth move is played, dropping the second move when the fifth is played, and so on. To implement this variant, we need to keep track of the sequence of moves, which we can do with a PlayerMove class, as in Example 5-20.

Example 5-20. A custom type suitable for tracking tic-tac-toe moves
namespace TicTacToe {
  public class PlayerMove {
    private string playerName;
    public string PlayerName {
      get { return playerName; }
      set { playerName = value; }
    }

    private int moveNumber;
    public int MoveNumber {
      get { return moveNumber; }
      set { moveNumber = value; }
    }

    public PlayerMove(string playerName, int moveNumber) {
      this.playerName = playerName;
      this.moveNumber = moveNumber;
    }
  }
}


Now, instead of using a simple string for each of the button object's content, we'll use an instance of PlayerMove in Example 5-21. Figure 5-6 shows the brilliance of such a change.

Example 5-21. Adding the PlayerMove as Button content
namespace TicTacToe {
  public partial class Window1 : Window {
    ...
    int moveNumber;

    void NewGame( ) {
      ...
      this.moveNumber = 0;
    }

    void cell_Click(object sender, RoutedEventArgs e) {
      ...
      // Set button content
      //button.Content = this.CurrentPlayer;
      button.Content =
        new PlayerMove(this.CurrentPlayer, ++this.moveNumber);
      ...
    }
    ...
  }
}

Figure 5-6. PlayerMove objects displayed without any special instructions


As you'll recall from Chapter 4, what's happening in Figure 5-6 is that the button doesn't have enough information to render a PlayerMove object, but we can fix that with a data template.

5.5.1. Data Templates

Recall from Chapter 4 that WPF allows you to define a data template, which is a tree of elements to expand in a particular context. Data templates are used to provide an application with the ability to render non-visual objects, as shown in Example 5-22.

Example 5-22. Setting a PlayerMove data template without styles
<?Mapping XmlNamespace="l" ClrNamespace="TicTacToe" ?>
<Window ... xmlns:local="local">
  <Window.Resources>
    <DataTemplate DataType="{x:Type local:PlayerMove}">
      <Grid>

        <TextBlock
          TextContent="{Binding Path=PlayerName}"
          FontSize ="32"
          FontWeight="Bold"
          VerticalAlignment="Center"
          HorizontalAlignment="Center" />
        <TextBlock
          TextContent="{Binding Path=MoveNumber}"
          FontSize="16"
          FontStyle="Italic"
          VerticalAlignment="Bottom"
          HorizontalAlignment="Right" />
      </Grid>
    </DataTemplate>
    ...
  </Window.Resources>
  ...

</Window>

Using the XAML mapping syntax introduced in Chapter 1, we've mapped the PlayerMover type into the XAML with the mapping directive and the xmlns attribute, which we've used as the data type of the data template. Now, whenever WPF sees a PlayerMove object, such as the content of all of our buttons, the data template will be expanded. In our case, the template consists of a grid to arrange two text blocks, one showing the player name in the middle of the button and one showing the move number in the bottom right, along with some other settings to make things pretty.

5.5.2. Data Templates with Style

However, these property settings are buried inside a data template several layers deep. Just as it's a good idea to take "magic numbers" out of your code, pulling them out and giving them names for easy maintenance, it's a good idea to move groups of settings into styles,[*] as in Example 5-23.

[*] Moving groups of settings into styles also allows for easier skinning and theming, as described in Chapter 6.

Example 5-23. Setting a PlayerMove data template with styles
<Window.Resources>
  <Style x:Key="CellTextStyle" TargetType="{x:Type TextBlock}">
    <Setter Property="FontSize" Value="32" />
    <Setter Property="FontWeight" Value="Bold" />
    <Setter Property="VerticalAlignment" Value="Center" />

    <Setter Property="HorizontalAlignment" Value="Center" />
  </Style>
  <Style x:Key="MoveNumberStyle" TargetType="{x:Type TextBlock}">
    <Setter Property="FontSize" Value="16" />
    <Setter Property="FontStyle" Value="Italic" />
    <Setter Property="VerticalAlignment" Value="Bottom" />

    <Setter Property="HorizontalAlignment" Value="Right" />
  </Style>
  <DataTemplate DataType="{x:Type l:PlayerMove}">
    <Grid>
      <TextBlock
        TextContent="{Binding Path=PlayerName}"
        Style="{StaticResource CellTextStyle}" />
      <TextBlock
        TextContent="{Binding Path=MoveNumber}"
        Style="{StaticResource MoveNumberStyle}" />

    </Grid>
  </DataTemplate>
</Window.Resources>

It's common to use styles, which set groups of properties, with data templates, which create groups of elements that have groups of properties. Figure 5-7 shows the result.

Figure 5-7. Showing objects of a custom type using data templates and styles


Still, as nice as Figure 5-7 is, the interaction is kind of boring given the capabilities of WPF. Let's see what we can do with style properties as the application is used.


©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