WPF中的模板(二)- ControlTemplate

一、TextBox控件的内部结构

首先,我们先利用Blend解开TextBox控件的内部结构。利用Blend新建一个WPF项目,在界面上添加一个TextBox。


我们看到,TextBox的四个角都是直角,我们现在试着把他的角变成圆角:
选中这个控件,右键->编辑模板->编辑副本。这里面我们选择编辑副本是在当前这个TextBox的模板之上进行修改。然后弹出如下图所示的对话框。其中名称指的是编辑后的Style的键值,如果选择全部应用所有的TextBox将都会设置该Style。定义位置指的是该Style代码存放的位置,可以是App级别的资源文件中、可以是当前的文档中,也可以是专门存放资源的自定义文档。


点击确定后,整个TextBox的结构展现在我们前面:

<Style x:Key="TextBoxStyle1" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
			<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
			<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
			<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
			<Setter Property="BorderThickness" Value="1"/>
			<Setter Property="Padding" Value="1"/>
			<Setter Property="AllowDrop" Value="true"/>
			<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
			<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
			<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
			<Setter Property="Template">
				<Setter.Value>
					<ControlTemplate TargetType="{x:Type TextBox}">
						<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
							<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
						</Microsoft_Windows_Themes:ListBoxChrome>
						<ControlTemplate.Triggers>
							<Trigger Property="IsEnabled" Value="false">
								<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
								<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
							</Trigger>
						</ControlTemplate.Triggers>
					</ControlTemplate>
				</Setter.Value>
			</Setter>
		</Style>


在最后一个Setter中,Template属性就是我们要设置的ControlTemplate。在这里,我们看到了整个TextBox的构成:Microsoft_Windows_Themes:ListBoxChrome下面包含一个ScrollViewer,我们要将TextBox的直角改成圆角,只需要将ListBoxChrome替换成Border,去掉不存在的属性,并设置其CornerRadius即可。修改后的代码如下:

<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"  SnapsToDevicePixels="true"
						CornerRadius="10">
							<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
						</Border>

运行结果如下:


通过上面的例子,可以总结如下:
1、ControlTemplate设置往往放到一个Style中,对应的属性是控件的Template属性,直接用ControlTemplate为Template赋值。
2、一个控件实际上由不同的子控件构成,这就是控件内部的VisualTree,VisualTree实际上就构成了整个控件的ControlTemplate的框架。另外,我们把在界面上可见的控件元素构成的节点树叫做LogicTree,需要和VisualTree进行区分。
3、从代码中可以看到很多的TemplateBinding,以BorderBrush="{TemplateBinding BorderBrush}"为例,我们设置的Border的BorderBrush通过TemplateBinding绑定了目标控件(TextBox)的BorderBrush,这样一旦TextBox的BorderBrush有任何的更新,都会及时的通知到Border并进行更新。
在这里,有一点需要说明一下,我们只看到TemplateBinding的Path是BorderBrush,却没有设置TemplateBinding的数据源Source,Binding是怎么找到目标控件的BorderBrush的呢,其实{TemplateBinding BorderBrush}就等同于{Binding BorderBrush RelativeSource={ RelativeSource TemplateParent}}。

二、ItemsControl的PanelTemplate
ItemsControl具有一个名为ItemsPanel的属性,他的数据类型是ItemsPanelTemplate。ItemsPanelTemplate也是一种控件的Template,它的作用是让我们有机会控制ItemsControl的条目容器。
下面我们将ListBox的Item由纵向排列改成横向排列:
首先,新建一个项目增加如下代码:

<Window
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
	x:Class="WpfApplication7.MainWindow"
	x:Name="Window"
	Title="MainWindow"
	Width="640" Height="480">


	<Grid x:Name="LayoutRoot">
		<ListBox Margin="80,24,72,26">
			<TextBlock Text="张三"/>
			<TextBlock Text="李四"/>
			<TextBlock Text="王五"/>
		</ListBox>
	</Grid>
</Window>

运行:

我们修改ListBoxItemsPanel,达到横向排列ListBoxItems的目的:

<Grid x:Name="LayoutRoot">
<ListBox Margin="80,24,72,26">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<TextBlock Text="张三"/>
<TextBlock Text="李四"/>
<TextBlock Text="王五"/>
</ListBox>
</Grid>

运行效果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值