1.从button的style说起
button有很多属性,我们在xaml中定义一个按钮时可以指定button的content、background、height、width等等。这些都是button的属性,而style也不例外也是button的一个属性,只是在给style属性赋值时不能简单的像height=“100”一样简单的设定一个字符串。先看一个简单的例子
我们定义了一个style对象,名字叫btnstyle,然后给2个button的style属性上赋值这个btnstyle对象,这是一个最简单的方式用来给button的style属性赋值。其他控件也是如此。
btnstyle这个对象用targettype指定此style可以被谁使用,这里指定时button。内部把button的background设置成绿色,height设置成50,width设置成50。我们可以看到界面上2个button都被成功改变了。
1.1button的style的作用
如上面的例子,我们在style中可以改变button的一些属性。如background、height、width。在style中我们可以设置控件的各个属性。也可以设置一些trigger,做一些属性检测。比如当某个属性的值等于多少时,改变另一个属性的值是多少。
1.2style中的trigger
设置2个简单的trigger:
当button的content=“123”时,button的foreground变成红色
当button的content=“456”时,button的width变成200
style的定义:
运行结果:
2.进入controltemplate
2.1有了style为什么还需要有controltemplate
通过上面的例子我们可以看出如果我们想要改变button的属性,或者做一些trigger监听,可以使用button的style属性来完成。
现在来思考两个问题:
问题1:button为什么长这个样子
问题2:如何改变每个控件的外观
问题1:button为什么长这个样子?
为什么一个button默认是矩形,不是圆形,为什么button能显示一些文本?
答案就是:控件模板定义了button默认的样子。所以问题2也有了答案,改变控件的外观需要修改它的控件模板。(style是不能改变控件的外观的)
2.2button的控件模板初步体验
控件模板是button的template属性,我们在资源中定义一个controltemplate,指定target为button,并写一个名字叫btnct。需要注意控件模板必须要指定key才行,另外为什么是controltemplate?因为template属性的类型是controlyemplate
看btnct这个控件模板的效果:发现button不显示任何东西,图中红色方框中没显示任何东西。button的外观由控件模板决定,btnct这个模板是空的,所以导致不显示任何东西。
我们需要在controltemplate标签内去定义button的外观,这里就完全由我们决定了,怎么写,他就怎么显示。
例如:我们想让一个button的外观长这个样子
好,这个按钮除了显示文本还能显示一个”x“,那我们开始布局。
运行结果确实显示了,但是感觉怪怪的,我们在进一步修改:添加一个背景色
现在显示背景色了,再进一步优化:让按钮的样子变成圆形
现在看我们已经改变了button的外观。
修改控件模板只会改变外观不会影响事件触发
到此为止我们已经通过修改控件模板成功改变的button的外观,这个圆形button除外观和原来的button不用,其他任何功能都一样,所有的事件都仍有效。
2.3templatebinding
好,现在我们来看控件模板的代码
<ControlTemplate TargetType="Button" x:Key="btnct"> <Border Background="Red" Height="50" Width="50" CornerRadius="25"> <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> <TextBlock Text="WPF"/> <TextBlock Margin="10 0 0 0" Text="x"/> </StackPanel> </Border> </ControlTemplate>
我们设置background hight width都是再控件模板内部写的,现在来看一个问题,在定义button时给content height width赋值,发现button并没有随之变化,这是为什么?
<Button Content="templatetest" Height="100" Width="100" Template="{StaticResource btnct}" Click="Button_Click"/>
因为我们在定义一个button时,wpf框架会从我们写的控件模板中解析这个button的外观,像content=”WPF“是写死在控件模板内部的,无论定义多少个button,content都显示WPF,那改如何解决这个问题?
很简单,只需要在button的content属性和控件模板内部的实际显示文本的控件产生一种关联即可。
我们看控件模板中真正显示WPF这个字符的是textblock
我们不能在这里写死,假设我们定义10个button,每个button显示文本也不同,需要把每个button的content属性和控件模板内部的textblock关联起来,具体语法如下:
可以看到button的content确实不一样了,同理我们在处理一下height和width
结果如下:
总结一下:控件模板是一个模板,当我们定义button时,button的外观取决于控件模板怎么定义,而控件模板内部的某些数据,可能需要被定义的这个button传递进去,这个传递通道使用templatebinding完成
3.style和controlyemplate的关联
button可以同时设置style和controltemplate,用style改变button的属性,用controltemplate改变button的外观。
3.1style能不能设置控件模板内部的控件?
同时设置style和controltemplate
<Button Content="333" Height="100" Width="100" Style="{StaticResource btnstyle}" Template="{StaticResource btnct}" Click="Button_Click"/>
style:
controltemplate
style中的property可以设置的属性都是targettype指定的类型的控件中的,那style能不能改变controltemplate中的border、stackpanel、textblock呢?
答案是:能改,但是不能直接改。
看下面这个图:button的style属性和template属性,style中能改controltemplate中的border的background吗?不能,虽然style中property可以设置background,但是这个background是由style中的targettype指定的,也就是button的background,并不是controltemplate中的border的。style中只能改button的background,把controltemplate中的border的background通过templatebinding到button的background。(注意:这里指的style是button的style)
3.2控件模板的trigger
控件模板中的trigger比style中的trigger一样,只多了一个targetname。控件模板中的trigger可以控件controltemplae标签内的所有对象,前提是设置一个name。(超出controltemplate标签的对象,无法被控制)
例如:鼠标悬浮,border变蓝色
再例如:鼠标悬浮:border变浅蓝,文本变绿色,x变橙色
3.3 style的trigger和控件模板中的trigger的优先级
button的显示其实是由控件模板内部的border来显示的,我们设置button的height width background,最后都通过template binding设置到了border身上。
如果style和控件模板的trigger起了冲突,谁起作用?直接说结论:控件模板起作用。(可以理解为:哪个trigger距离被控对象越近,哪个trigger优先级越高)
4.逻辑树(logic tree)和视觉树(visual tree)
速记:
1.在window窗体上布局的控件组成的逻辑是逻辑树
2.逻辑树+控件的控件模板内部的控件=视觉树
3.视觉树包含逻辑树
5.ContentPresenter
button的content属性是一个object类型的对象,也就意味着,可以给content赋值任何对象,但在我们写的这个控件模板中,只能写字符串,因为控件模板内部使用了textblock。如果我给content放一个image对象,就显示不出来了,
这时候需要ContentPresenter登场,只需要在控件模板内部放一个这个就可以了,它相当于一个占位符,我们传递什么,他就会显示什么
<button.content>默认可以省掉
下面是另一个控件模板:(想说的是控件模板内部其实也是怎么布局的问题)
6.其他问题
6.1style是属性,template是属性。style中不可以再控制style,可以设置template
不可以在style中再设置style
可以在style中设置template
6.2全局引用控件模板style不屑key,则程序范围内的控件自动引用,控件模板不写key不行,写了key就得手动赋值,把控件模板写在style中即可则程序范围内的控件自动引用
标签:控件,style,button,controltemplate,wpf,模板,属性 From: https://www.cnblogs.com/1024E/p/17516399.html