Styles and Control Templates
(Page 1 of 4 )
A style is a set of properties applied to content used for visual rendering. If you want to learn more about styles in Windows, you've come to the right place. This article is excerpted from chapter five of the book
Programming Windows Presentation Foundation, written by Chris Sells and Ian Griffiths (O'Reilly; ISBN: 0596101139). Copyright © 2006 O'Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O'Reilly Media.
In a word processing document, a “style” is a set of properties to be applied to ranges of content—e.g., text, images, etc. For example, the name of the style I’m using now is called “Normal,Body,b” and for this document in pre-publication, that means a font family of Times, a size of 10, and full justification. Later on in the document, I’ll be using a style called “Code,x,s” that will use a font family of Courier New, a size of 9, and left justification. Styles are applied to content to produce a certain look when the content is rendered.
In WPF, a style is also a set of properties applied to content used for visual rendering. A style can be used to set properties on an existing visual element, such as setting the font weight of a Buttoncontrol, or it can be used to define the way an object looks, such as showing the name and age from aPersonobject. In addition to the features in word processing styles, WPF styles have specific features for building applications, including the ability to associate different visual effects based on user events, provide entirely new looks for existing controls, and even designate rendering behavior for non-visual objects. All of these features come without the need to build a custom control (although that’s still a useful thing to be able to do, as discussed in Chapter 9).
Without Styles As an example of how styles can make themselves useful in WPF, let’s take a look at a simple implementation of tic-tac-toe in Example 5-1.
Example 5-1. A simple tic-tac-toe layout
<!-- Window1.xaml -->
<Window
x:Class="TicTacToe.Window1"
xmlns=http://schemas.microsoft.com/ winfx/avalon/2005
xmlns:x=http://schemas.microsoft.com/ winfx/xaml/2005
Text="TicTacToe">
<!-- the black background lets the tic-tac-toe -->
<!-- crosshatch come through on the margins -->
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Margin="0,0,2,2" Grid.Row="0" Grid.Column="0" x:Name="cell00" />
<Button Margin="2,0,2,2" Grid.Row="0" Grid.Column="1" x:Name="cell01" />
<Button Margin="2,0,0,2" Grid.Row="0" Grid.Column="2" x:Name="cell02" />
<Button Margin="0,2,2,2" Grid.Row="1" Grid.Column="0" x:Name="cell10" />
<Button Margin="2,2,2,2" Grid.Row="1" Grid.Column="1" x:Name="cell11" />
<Button Margin="2,2,0,2" Grid.Row="1" Grid.Column="2" x:Name="cell12" />
<Button Margin="0,2,2,0" Grid.Row="2" Grid.Column="0" x:Name="cell20" />
<Button Margin="2,2,2,0" Grid.Row="2" Grid.Column="1" x:Name="cell21" />
<Button Margin="2,2,0,0" Grid.Row="2" Grid.Column="2" x:Name="cell22" />
</Grid>
</Window>
This grid layout arranges a set of nine buttons in a 3× 3 grid of tic-tac-toe cells, using the margins on the button for the tic-tac-toe crosshatch. A simple implementation of the game logic in the XAML code-behind file looks like Example 5-2.
Example 5-2. A simple tic-tac-toe implementation
// Window1.xaml.cs
...
namespace TicTacToe {
public partial class Window1 : Window {
// Track the current player (X or O)
string currentPlayer;
// Track the list of cells for finding a winner etc.
Button[] cells;
public Window1() {
InitializeComponent();
// Cache the list of buttons and handle their clicks
this.cells = new Button[] { this.cell00, this.cell01, ... };
foreach( Button cell in this.cells ) {
cell.Click += cell_Click;
}
// Initialize a new game
NewGame();
}
// Wrapper around the current player for future expansion,
// e.g. updating status text with the current player
string CurrentPlayer {
get { return this.currentPlayer; }
set { this.currentPlayer = value; }
}
// Use the buttons to track game state
void NewGame() {
foreach( Button cell in this.cells ) {
cell.Content = null;
}
CurrentPlayer = "X";
}
void cell_Click(object sender, RoutedEventArgs e) {
Button button = (Button)sender;
// Don't let multiple clicks change the player for a cell
if( button.Content != null ) { return; }
// Set button content
button.Content = CurrentPlayer;
// Check for winner or a tie
if( HasWon(this.currentPlayer) ) {
MessageBox.Show("Winner!", "Game Over");
NewGame();
return;
}
else if( TieGame() ) {
MessageBox.Show("No Winner!", "Game Over");
NewGame();
return;
}
// Switch player
if( CurrentPlayer == "X" ) {
CurrentPlayer = "O";
}
else {
CurrentPlayer = "X";
}
}
// Use this.cells to find a winner or a tie
bool HasWon(string player) {...}
bool TieGame() {...}
}
}
Our simple tic-tac-toe logic uses strings to represent the players and uses the buttons themselves to keep track of the game state. As each button is clicked, we set the content to the string indicating the current player and switch players. When the game is over, the content for each button is cleared. The middle of a game looks like Figure 5-1.

Figure 5-1. A simple tic-tac-toe game
Notice in Figure 5-1 how the grid background comes through from the margin. These spacers almost make the grid look like a drawn tic-tac-toe board (although we’ll do better later). However, if we’re really looking to simulate a hand-drawn game, we’ve got to do something about the size of the font used on the buttons; it doesn’t match the thickness of the lines.
One way to fix this problem is by setting the size and weight for each of the Button objects, as in Example 5-3.
Example 5-3. Setting control properties individually
<Button FontSize="32" FontWeight="Bold" ... x:Name="cell00" />
<Button FontSize="32" FontWeight="Bold"... x:Name="cell01" />
<Button FontSize="32" FontWeight="Bold"... x:Name="cell02" />
<Button FontSize="32" FontWeight="Bold"... x:Name="cell10" />
<Button FontSize="32" FontWeight="Bold"... x:Name="cell11" />
<Button FontSize="32" FontWeight="Bold"... x:Name="cell12" />
<Button FontSize="32" FontWeight="Bold"... x:Name="cell20" />
<Button FontSize="32" FontWeight="Bold"... x:Name="cell21" />
<Button FontSize="32" FontWeight="Bold"... x:Name="cell22" />
While this will make the X’s and O’s look better according to my visual sensibilities today, if I want to change it later, I’ve now committed myself to changing both properties in nine separate places, which is a duplication of effort that offends my coding sensibilities. I’d much prefer to refactor my decisions about the look of my tic-tac-toe cells into a common place for future maintenance. That’s where styles come in handy.
Next: Inline Styles >>
More XML Articles
More By O'Reilly Media
|
This article is excerpted from chapter five of the book Programming Windows Presentation Foundation, written by Chris Sells and Ian Griffiths (O'Reilly; ISBN: 0596101139). Check it out today at your favorite bookstore. Buy this book now.
|
|