原文:《Programming WPF》翻译 第5章 1.不使用样式

作为一个样式如何使其在WPF使用的例子,,让我们看一下TTT简单的实现,如示例5-1。

示例5-1

<!-- 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>

这个grid的外观上排列了一组9个按钮在一个3X3栅格的TTT单元中,在按钮上使用了页面空白为了TTT的交叉线阴影。对游戏逻辑的一个简单的实现,在xaml后台代码中,如示例5-2所示。

示例5-2

// 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( ) {}

  }

}

我们的简单TTT逻辑使用字符串代表玩家,使用按钮来跟踪游戏状态。当点击任意一个按钮时,我们将内容设置为字符串,用来象征当前玩家以及转换玩家。当游戏结束的时候,每一个按钮上的内容都会被清除。游戏中的截图如图5-1。

图5-1





注意到图5-1中,grid的背景来自页面的空白。这些空白差不多使grid看上去像一个可绘制的TTT木板(虽然我们将来会做的更好)。然而,如果我们真的指望模仿一个手绘的游戏,我们已经对按钮上的字体大小做了设置,但并没匹配到线条的厚度。

一种修复这个问题的方法是为每一个按钮对象设置字体和宽度,如示例5-3。

示例5-3

<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" />

依照我的视觉敏感性,今天,虽然这样做使得X的和O的外观更好,一旦我以后想改动它,我就要负责在9个独立的地方改变这些属性,这是重复性的努力——违反了我的编码敏感性。我宁愿重制我的决定——为了以后的维护,将我的TTT单元的外观放在一个共同的地方。这是样式派得上用场的地方。

《Programming WPF》翻译 第5章 1.不使用样式的更多相关文章

  1. 《Programming WPF》翻译 第6章 2.资源与样式

    原文:<Programming WPF>翻译 第6章 2.资源与样式 WPF的样式机制以来于资源体系来定位样式.正如你在第5章看到的,样式在元素的资源片段中定义,而且样式通过其名字被引用, ...

  2. 《Programming WPF》翻译 第5章 4.元素类型样式

    原文:<Programming WPF>翻译 第5章 4.元素类型样式 命名样式非常有用,当你得到一组属性并应用到特点的元素上.然而,如果你想要应用一个统一的样式到所有确定元素类型的实例, ...

  3. 《Programming WPF》翻译 第5章 2.内嵌样式

    原文:<Programming WPF>翻译 第5章 2.内嵌样式 每一个“可样式化”的WPF元素都有一个Style属性,可以在内部设置这个属性--使用XAML属性-元素的语法(在第一章讨 ...

  4. 《Programming WPF》翻译 第9章 5.默认可视化

    原文:<Programming WPF>翻译 第9章 5.默认可视化 虽然为控件提供一个自定义外观的能力是有用的,开发者应该能够使用一个控件而不用必须提供自定义可视化.这个控件应该正好工作 ...

  5. 《Programming WPF》翻译 第9章 6.我们进行到哪里了?

    原文:<Programming WPF>翻译 第9章 6.我们进行到哪里了? 只有当任何内嵌控件都没有提供你需要的底层行为时,你将要写一个自定义控件.当你写一个自定义控件,你将要使用到依赖 ...

  6. 《Programming WPF》翻译 第9章 4.模板

    原文:<Programming WPF>翻译 第9章 4.模板 对一个自定义元素最后的设计考虑是,它是如何连接其可视化的.如果一个元素直接从FrameworkElement中派生,这将会适 ...

  7. 《Programming WPF》翻译 第9章 3.自定义功能

    原文:<Programming WPF>翻译 第9章 3.自定义功能 一旦你挑选好一个基类,你将要为你的控件设计一个API.大部分WPF元素提供属性暴露了多数功能,事件,命令,因为他们从框 ...

  8. 《Programming WPF》翻译 第9章 2.选择一个基类

    原文:<Programming WPF>翻译 第9章 2.选择一个基类 WPF提供了很多类,当创建一个自定义元素时,你可以从这些类中派生.图9-1显示了一组可能作为类--可能是合适的基类, ...

  9. 《Programming WPF》翻译 第9章 1.自定义控件基础

    原文:<Programming WPF>翻译 第9章 1.自定义控件基础 在写一个自定义控件之前,你需要问的第一个问题是,我真的需要一个自定义控件吗?一个写自定义控件的主要原因是为了用户界 ...

随机推荐

  1. Android开发多线程断点续传下载器

    使用多线程断点续传下载器在下载的时候多个线程并发可以占用服务器端更多资源,从而加快下载速度,在下载过程中记录每个线程已拷贝数据的数量,如果下载中断,比如无信号断线.电量不足等情况下,这就需要使用到断点 ...

  2. SSH自动部署(转)

    我的是windows环境,目前开发的过程中,有些项目需要一下子部署到很多的linux服务器上.写了个脚本能够自动上传文件和执行部署任务.完成这个任务需要的条件包括SSH配置和一个执行脚本. 准备 1. ...

  3. Oracle中对列加密的方法

    Oracle中对列加密的方法 2011-12-22 17:21:13 分类: Linux Oracle支持多种列加密方式: 1,透明数据加密(TDE):create table encrypt_col ...

  4. uiautomatorviewer 识别android微信元素报错

    org.xml.sax.SAXParseException; systemId: file:/C:/Users/xxxxxxxxx/AppData/Local/Temp/uiautomatorview ...

  5. js高级程序设计(第三版)学习笔记(第一版)

    ecma:欧洲计算机制造商协会iso/iec:国际标准化和国际电工委员会 dom级别(10*)文档对象模型1:DOM核心(映射基于xml文档)与dom html(在dom核心基础上)2:对鼠标,事件, ...

  6. Go程序GC优化经验分享

    http://1234n.com/?post/yzsrwa 最近一段时间对<仙侠道>的服务端进行了一系列针对GC的调优,这里跟各位分享一下调优的经验. 游戏第一次上线的时候,大部分精力都投 ...

  7. 内存测试工具memtester

    Memtester是用户态工具,用于测试内存子系统的故障.非常方便,支持32位 或64位Unix-like系统.对于硬件开发开发者来说,memtester可以定位到物理地址. 1. 安装 下载地址ht ...

  8. c语言10个经典小程序

    [程序1] 题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. ...

  9. [CSAPP笔记][第十二章并发编程]

    第十二章 并发编程 如果逻辑控制流在时间上是重叠,那么它们就是并发的(concurrent).这种常见的现象称为并发(concurrency). 硬件异常处理程序,进程和Unix信号处理程序都是大家熟 ...

  10. SpinLock(自旋锁)

    SpinLock(自旋锁) SpinLock 结构是一个低级别的互斥同步基元,它在等待获取锁时进行旋转. 在多核计算机上,当等待时间预计较短且极少出现争用情况时,SpinLock 的性能将高于其他类型 ...