前言
每次开发滑块控件的样式都要花很久去读样式代码,感觉有点记不牢,所以特此备忘。
自定义滑块样式
首先创建项目,添加slider控件。
然后获取slider的window样式,如下图操作。
然后弹出界面如下.我们点击确定。
点击确定后,我们的页面的resources中,增加了一系列样式代码,而滑块代码会被修改为如下样子:
<slider horizontalalignment="left" width="200" verticalalignment="top" style="{dynamicresource sliderstyle1}"/>
可以看到,系统为我们的slider控件增加了样式——style="{dynamicresource sliderstyle1}"
现在我们查看样式sliderstyle1,f12跟踪到定义。
<style x:key="sliderstyle1" targettype="{x:type slider}"> <setter property="stylus.ispressandholdenabled" value="false"/> <setter property="background" value="transparent"/> <setter property="borderbrush" value="transparent"/> <setter property="foreground" value="{staticresource sliderthumb.static.foreground}"/> <setter property="template" value="{staticresource sliderhorizontal}"/> <style.triggers> <trigger property="orientation" value="vertical"> <setter property="template" value="{staticresource slidervertical}"/> </trigger> </style.triggers> </style>
上述代码中我们可以看发现slider使用的模板是sliderhorizontal,但当他的排列方向为vertical时,则使用slidervertical模板。
因为slider控件默认是横向布局,所以我们先修改sliderhorizontal模板,对slider进行下美化。
同样,我们继续f12跟进sliderhorizontal的定义。
<controltemplate x:key="sliderhorizontal" targettype="{x:type slider}"> <border x:name="border" borderbrush="{templatebinding borderbrush}" borderthickness="{templatebinding borderthickness}" background="{templatebinding background}" snapstodevicepixels="true"> <grid> <grid.rowdefinitions> <rowdefinition height="auto"/> <rowdefinition height="auto" minheight="{templatebinding minheight}"/> <rowdefinition height="auto"/> </grid.rowdefinitions> <tickbar x:name="toptick" fill="{templatebinding foreground}" height="4" margin="0,0,0,2" placement="top" grid.row="0" visibility="collapsed"/> <tickbar x:name="bottomtick" fill="{templatebinding foreground}" height="4" margin="0,2,0,0" placement="bottom" grid.row="2" visibility="collapsed"/> <border x:name="trackbackground" borderbrush="{staticresource sliderthumb.track.border}" borderthickness="1" background="{staticresource sliderthumb.track.background}" height="4.0" margin="5,0" grid.row="1" verticalalignment="center"> <canvas margin="-6,-1"> <rectangle x:name="part_selectionrange" fill="{dynamicresource {x:static systemcolors.highlightbrushkey}}" height="4.0" visibility="hidden"/> </canvas> </border> <track x:name="part_track" grid.row="1"> <track.decreaserepeatbutton> <repeatbutton command="{x:static slider.decreaselarge}" style="{staticresource repeatbuttontransparent}"/> </track.decreaserepeatbutton> <track.increaserepeatbutton> <repeatbutton command="{x:static slider.increaselarge}" style="{staticresource repeatbuttontransparent}"/> </track.increaserepeatbutton> <track.thumb> <thumb x:name="thumb" focusable="false" height="18" overridesdefaultstyle="true" template="{staticresource sliderthumbhorizontaldefault}" verticalalignment="center" width="11"/> </track.thumb> </track> </grid> </border> <controltemplate.triggers> <trigger property="tickplacement" value="topleft"> <setter property="visibility" targetname="toptick" value="visible"/> <setter property="template" targetname="thumb" value="{staticresource sliderthumbhorizontaltop}"/> <setter property="margin" targetname="trackbackground" value="5,2,5,0"/> </trigger> <trigger property="tickplacement" value="bottomright"> <setter property="visibility" targetname="bottomtick" value="visible"/> <setter property="template" targetname="thumb" value="{staticresource sliderthumbhorizontalbottom}"/> <setter property="margin" targetname="trackbackground" value="5,0,5,2"/> </trigger> <trigger property="tickplacement" value="both"> <setter property="visibility" targetname="toptick" value="visible"/> <setter property="visibility" targetname="bottomtick" value="visible"/> </trigger> <trigger property="isselectionrangeenabled" value="true"> <setter property="visibility" targetname="part_selectionrange" value="visible"/> </trigger> <trigger property="iskeyboardfocused" value="true"> <setter property="foreground" targetname="thumb" value="blue"/> </trigger> </controltemplate.triggers> </controltemplate>
sliderhorizontal模板的定义比较多,这里直接定义到重点内容——轨道。
首先定位到代码【border x:name="trackbackground"】,这里的trackbackground是控制滑块背景颜色的,我们修改其背景颜色和边框颜色。
<border x:name="trackbackground" borderbrush="red" borderthickness="1" background="yellow" height="4.0" margin="5,0" grid.row="1" verticalalignment="center"> <canvas margin="-6,-1"> <rectangle x:name="part_selectionrange" fill="{dynamicresource {x:static systemcolors.highlightbrushkey}}" height="4.0" visibility="hidden"/> </canvas> </border>
得到效果如下:
但我们有时候需要拖动前后颜色不一样,此时就靠背景修改就不够了。
在sliderhorizontal模板中找到decreaserepeatbutton和increaserepeatbutton;这两个一个是拖动前覆盖颜色,一个是拖动后覆盖颜色。
修改代码如下:
<track x:name="part_track" grid.row="1"> <track.decreaserepeatbutton> <repeatbutton height="4" background="gray" command="{x:static slider.decreaselarge}" style="{staticresource repeatbuttontransparent}"/> </track.decreaserepeatbutton> <track.increaserepeatbutton> <repeatbutton height="4" background="green" command="{x:static slider.increaselarge}" style="{staticresource repeatbuttontransparent}"/> </track.increaserepeatbutton> <track.thumb> <thumb x:name="thumb" focusable="false" height="18" overridesdefaultstyle="true" template="{staticresource sliderthumbhorizontaldefault}" verticalalignment="center" width="11"/> </track.thumb> </track>
得到效果如下:
注意这里的height一定要给值。
现在,我们设置好了轨道,可当前的滑块的颜色我们有点不太满意,所以我们再来处理下滑块。
滑块模板的模板是上方代码中粉色标记的代码——thumb。
可以看到thumb使用的是sliderthumbhorizontaldefault模板,所以,我们继续f12跟进sliderthumbhorizontaldefault查看它的定义。
<controltemplate x:key="sliderthumbhorizontaldefault" targettype="{x:type thumb}"> <grid horizontalalignment="center" uselayoutrounding="true" verticalalignment="center"> <path x:name="grip" data="m 0,0 c0,0 11,0 11,0 11,0 11,18 11,18 11,18 0,18 0,18 0,18 0,0 0,0 z" fill="{staticresource sliderthumb.static.background}" stretch="fill" snapstodevicepixels="true" stroke="{staticresource sliderthumb.static.border}" strokethickness="1" uselayoutrounding="true" verticalalignment="center"/> </grid> <controltemplate.triggers> <trigger property="ismouseover" value="true"> <setter property="fill" targetname="grip" value="{staticresource sliderthumb.mouseover.background}"/> <setter property="stroke" targetname="grip" value="{staticresource sliderthumb.mouseover.border}"/> </trigger> <trigger property="isdragging" value="true"> <setter property="fill" targetname="grip" value="{staticresource sliderthumb.pressed.background}"/> <setter property="stroke" targetname="grip" value="{staticresource sliderthumb.pressed.border}"/> </trigger> <trigger property="isenabled" value="false"> <setter property="fill" targetname="grip" value="{staticresource sliderthumb.disabled.background}"/> <setter property="stroke" targetname="grip" value="{staticresource sliderthumb.disabled.border}"/> </trigger> </controltemplate.triggers> </controltemplate>
从上述代码中可以看到,滑块定义很简单,布局就是一个grid里放了一个path,事件响应只有3个。
下面为修改path的fill填充色和stroke的划线颜色如下:
<path x:name="grip" data="m 0,0 c0,0 11,0 11,0 11,0 11,18 11,18 11,18 0,18 0,18 0,18 0,0 0,0 z" fill="red" stretch="fill" snapstodevicepixels="true" stroke="blue" strokethickness="1" uselayoutrounding="true" verticalalignment="center"/>
得到效果如下:
现在,我们觉得矩形的滑块不好看,需要用椭圆形的滑块,那么,我们再来处理下滑块。
首先删除thumb里定义的宽和高,因为不删除它们,模板里的宽高会受此限制。
删除后如下:
<track.thumb> <thumb x:name="thumb" focusable="false" overridesdefaultstyle="true" template="{staticresource sliderthumbhorizontaldefault}" verticalalignment="center" /> </track.thumb>
现在我们再来修改sliderthumbhorizontaldefault模板。
在模板里找到path,修改他的data,之前他的data是自己画的一个矩形,现在我们给他改为椭圆形,并且给path重新设置宽高,如下:
<path x:name="grip" width="20" height="20" fill="red" stretch="fill" snapstodevicepixels="true" stroke="blue" strokethickness="1" uselayoutrounding="true" verticalalignment="center"> <path.data> <ellipsegeometry center="10,10" radiusx="10" radiusy="10"></ellipsegeometry> </path.data> </path>
我们得到效果如下:
可以看到,图中的滑块是个圆形,而我们需要的是一个椭圆形。
处理很简单,修改path的width即可,我们该为14,得到效果如下:
当然,我们既然可以通过修改样式设计椭圆形滑块,就也可以设计其他形状滑块,比如,我们修改path如下,获得斜角四边形滑块:
<path x:name="grip" width="14" height="20" fill="red" stretch="fill" snapstodevicepixels="true" stroke="blue" strokethickness="1" uselayoutrounding="true" verticalalignment="center"> <path.data> <pathgeometry> <pathgeometry.figures> <pathfigure startpoint="0,0" isclosed="true"> <linesegment point="0,0" /> <linesegment point="110,0" /> <linesegment point="70,40" /> <linesegment point="-40,40" /> </pathfigure> </pathgeometry.figures> </pathgeometry> </path.data> </path>
效果图如下:
修改代码如下,设置三角形滑块:
<path x:name="grip" width="14" height="20" fill="red" stretch="fill" snapstodevicepixels="true" stroke="blue" strokethickness="1" uselayoutrounding="true" verticalalignment="center"> <path.data> <pathgeometry> <pathgeometry.figures> <pathfigure startpoint="0,0" isclosed="true"> <linesegment point="30,0" /> <linesegment point="15,100" /> </pathfigure> </pathgeometry.figures> </pathgeometry> </path.data> </path>
效果图如下:
----------------------------------------------------------------------------------------------------
上述代码设置的都是水平方向的滑块样式,垂直方向的滑块样式设置同理,只要从模板slidervertical开始,以此处理修改即可。
----------------------------------------------------------------------------------------------------
到此wpf滑块控件(slider)的自定义样式就已经讲解完成了。
代码已经传到github上了,欢迎大家下载。
github地址:https://github.com/kiba518/wpfslider
----------------------------------------------------------------------------------------------------
注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!
若您觉得这篇文章还不错,请点击下方的【推荐】,非常感谢!