原文:
《Programming WPF》翻译 第5章 5.数据模板和样式
让我们想象一下我们想要实现TTT更有娱乐性的一个版本(这是大部分游戏中最重要的特色)。例如,TTT的一种变体允许玩家每次只能占据3个格子,去除第一步在下第四步的时候,去除第二步在下第五步的时候,,以此类推。为了实现这个变体,我们需要保持对每一步按顺序跟踪——可以利用PlayMover类,如示例5-20。
示例5-20
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;
}
}
}
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;
}
}
}
现在,取代以为每个按钮对象的内容使用一个简单的字符串,我们将用示例
示例5-21
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);
}
}
}
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);
}
}
}
图
5-6正如你回想到的,在第四章,图5-6所发生的是,按钮没有足够多的信息生成一个PlayMover对象,但是我们可以通过一个数据模板修复它。
5.5.1数据模板
回忆第四章,WPF允许你定义一个数据模板,这是一棵元素树,可以在特定的上下文中扩展。数据模板用于提供一个应用程序生成非可视化外观对象的能力,正如示例5-22所示。
示例5-22
<?
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 >
< 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 >
使用在第一章介绍的
5.5.2带样式的数据绑定
尽管如此,这些属性设置深埋在数据模板的很深层。正像这是一个好的想法将“魔力数字”移出你的代码,将它们拉出去并给它们一个易于管理的名称,这是一个好的想法将成组的设置移动到样式中,如示例5-23所示。
*将成组的设置移动到样式中,还顾及皮肤和主题,在第六章会介绍。
示例5-23
<
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 >
< 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 >
使用样式是很通常的,从而可以使用数据模板设置成组的属性,创建带有大量属性的大量元素。图
图5-7
仍然,像图5-7一样漂亮,交互作用是一种WPF给予的令人厌烦的能力。让我们看一下使用在应用程序中使用样式属性我们都能做些什么。