《Programming WPF》翻译 第5章 7.控件模板

简介: 原文:《Programming WPF》翻译 第5章 7.控件模板如果仔细的看我们当前的TTT游戏,会发现Button对象并没有完全为我们工作。哪些TTT面板有内圆角? 图5-14 这里,我们真正需要的是能够保持按钮的行为,如支持内容和点击事件,但是我们想要接管这些按钮的外观。
原文: 《Programming WPF》翻译 第5章 7.控件模板

如果仔细的看我们当前的TTT游戏,会发现Button对象并没有完全为我们工作。哪些TTT面板有内圆角?

5-14



这里,我们真正需要的是能够保持按钮的行为,如支持内容和点击事件,但是我们想要接管这些按钮的外观。
WPF允许这种方式,因为内在的控件创建的时候是缺少外观性的,例如,他们提供行为,但是外观可以被完全包装在客户端控件的外面。

还记得我们是如何使用数据模板,来为非可视化对象提供外观的么?我们能够使用控件模板对控件做同样的事情,这将是一组StoryBoard,触发器,以及大多数重要的提供控件外观的元素。

为了修复我们的按钮外观,我们创建了一个控件模板的资源。让我们从示例5-31出发,这是一个带有简单的矩形,和以后考虑如何显示实际的按钮内容。

示例5-31

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

5-15 显示了设置一个单独按钮的Template 属性的结果。

注意到按钮过去样子的痕迹(保留在图5-15中)。不幸的是,看不到我们的矩形的痕迹。问题在于,缺少一个显示的填充设置,这个矩形的默认填充是透明的,显示grid的黑色背景。让我们将其设置为喜欢的万圣节颜色:

< ControlTemplate  x:Key =”ButtonTemplate”>
            
<Rectangle Fill =”Orange”  />
</ ControlTemplate >

5-15

现在我们在这个地方,如图5-16所示。

5-16


注意,拐角处是如何成直角的?而且,一旦你点击了按钮,你不会获得压下的效果。(而且我没有意味“一个不爽的感觉”)

5.7.1控件模板和样式

注意到我们在控件模板上取得的一些成果,让我们将其复制到其它按钮上。我们可以手动设置每个按钮上的模板属性,或者,作为最普通的,我们可以用按钮的样式包装这个模板控件。如示例5-32

示例5-32

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


正如示例

5-32 所示,模板属性和使用样式设置是一样的。图5-17 显示了结果。

5-17



仍然,橙色是不和谐的,尤其是因为白色背景样式上的设定。我们可以用模板绑定来解决这个问题。

5.7.2模板绑定

为了回到我们的白色按钮,我们可以硬编码将矩形填充为白色,但是如果样式要改变它呢(正如在我们中断的动画)?取代以硬编码填充矩形,我们使用模板绑定来将模板应用到控件属性中,正如示例5-33所示。

示例5-33

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


模板绑定就像数据绑定,除了绑定的属性来自被你替换了模板的控件(称为模板化的父级别)。在我们的情形中,像

Background HorizontalContentAlignment 等等,是美丽的游戏,用来模板绑定自父级别。同时,像数据绑定,模板绑定是相当小巧的——用来保持模板中的条目属性是最新的,随着外界的属性改变,如被样式和动画设置等等。举例来说,图5-18 显示了混淆矩形的Fill 属性到按钮的Background 属性的效果——仍然适当地通过我们的点击动画和鼠标盘旋的行为。

5-18



尽管如此,我们还没有彻底到达。如果我们将要改变图画样品,这样图
5-18已经变为了一个可玩的游戏,我们不得不显示所有的移动。为了这么做,我们需要一个内容推荐者。

5.7.3内容推荐者

如果你曾经被广告牌或汽车站长椅上写着的“这里是你的广告!”所驱动,然后这就是所有你需要知道的理解内容推荐者。内容推荐者等价于WPF中的“这里是你的内容”,允许内容由插入的ContentContainer控件保持在运行期。

在我们的情形中,内容是可视化的PlayerMove对象。取代以复制所有的工作到按钮新的控件模板中,我们只想要去除它在正确的地方。内容推荐者的工作是获取内容——由内容模板化的父级别提供,以及所有必须要显示的事物,包括样式,触发器等等。内容推荐者可以添加到你的模板中——无论在哪里看到的模板(包括多次,如果它使你愉快,例如生成一个下拉阴影)。在我们的情形中,我们在示例5-34中组成一个内容推荐者,使用第2章的技术在grid中放一个矩形。

示例5-34

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


在示例

5-34 中,内容推荐者的Content 属性绑定到ContentControl.Content 属性,为了内容成功使用。作为使用样式,我们可以避免给模板绑定属性名称加上类的前缀,通过在ContentTemplate 元素上设置TargetAttribute 属性。

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

进一步,在恰当的位置使用TargetType 属性,你可以一起去除显示地模板绑定到Content ,属性上,同时它会进行自动设置。

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

内容推荐者是我们需要的全部,使得我们的游戏回到具有功能性,正如图5-19 所示。

5-19



5.7.4真实的工作

最后一小块工作是获取右间隙。由于内容推荐者没有自身的Padding属性,我们不能直接绑定Padding属性(它也没有Background属性,这是为什么我们使用Rectangle和其Fill属性)。因为这些属性并不匹配内容推荐者,你不得不找到映射或者组合提供这些功能的元素。例如,padding是控件中一定数量的空白,另一方面,Margin是控件周围一定数量的空白。由于他们都是同样的类型,System.Windows.Thickness,如果我们可以映射按钮中的Padding到内容控件的外面。我们的TTT游戏看起来就会很漂亮:

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

5-20 显示了我们最终的TTT 变体。

5-20



就像
PaddingMargin间的映射,建立一个元素提供给你想要的外观,并且从父级别的模板绑定到相应的属性,将要做很多的工作来创建你自己的控件模板。

目录
相关文章
|
1月前
|
C# 开发者 Windows
基于Material Design风格开源、易用、强大的WPF UI控件库
基于Material Design风格开源、易用、强大的WPF UI控件库
128 0
|
1月前
|
C#
浅谈WPF之装饰器实现控件锚点
使用过visio的都知道,在绘制流程图时,当选择或鼠标移动到控件时,都会在控件的四周出现锚点,以便于修改大小,移动位置,或连接线等,那此功能是如何实现的呢?在WPF开发中,想要在控件四周实现锚点,可以通过装饰器来实现,今天通过一个简单的小例子,简述如何在WPF开发中,应用装饰器,仅供学习分享使用,如有不足之处,还请指正。
83 1
|
10月前
|
C# Windows
WPF技术之图形系列Polygon控件
WPF Polygon是Windows Presentation Foundation (WPF)框架中的一个标记元素,用于绘制多边形形状。它可以通过设置多个点的坐标来定义多边形的形状,可以绘制任意复杂度的多边形。
569 0
|
10月前
|
C# Windows
WPF技术之RichTextBox控件
WPF RichTextBox是Windows Presentation Foundation (WPF)中提供的一个强大的文本编辑控件,它可以显示富文本格式的文本,支持多种文本处理操作。
392 0
|
1月前
|
前端开发 C# 容器
浅谈WPF之控件拖拽与拖动
使用过office的visio软件画图的小伙伴都知道,画图软件分为两部分,左侧图形库,存放各种图标,右侧是一个画布,将左侧图形库的图标控件拖拽到右侧画布,就会生成一个新的控件,并且可以自由拖动。那如何在WPF程序中,实现类似的功能呢?今天就以一个简单的小例子,简述如何在WPF中实现控件的拖拽和拖动,仅供学习分享使用,如有不足之处,还请指正。
134 2
|
1月前
|
文字识别 C# 开发者
WPF开源的一款免费、开箱即用的翻译、OCR工具
WPF开源的一款免费、开箱即用的翻译、OCR工具
|
10月前
|
数据挖掘 数据处理 C#
WPF技术之DataGrid控件
WPF DataGrid是一种可以显示和编辑数据的界面控件。它可以作为表格形式展示数据,支持添加、删除、修改、排序和分组操作。
208 0
|
7月前
|
算法 C# UED
浅谈WPF之控件模板和数据模板
WPF不仅支持传统的Windows Forms编程的用户界面和用户体验设计,同时还推出了以模板为核心的新一代设计理念。在WPF中,通过引入模板,将数据和算法的“内容”和“形式”进行解耦。模板主要分为两大类:数据模板【Data Template】和控件模板【Control Template】。
124 8
|
1月前
|
C# 开发者 C++
一套开源、强大且美观的WPF UI控件库
一套开源、强大且美观的WPF UI控件库
192 0
|
10月前
|
XML C# 数据格式
WPF技术之DocumentViewer控件
WPF 的 DocumentViewer 是一个强大的控件,用于在应用程序中显示各种类型的文档,如 XPS(XML Paper Specification)、FlowDocument 和 FixedDocument 等。
1314 1