WPF换肤设计原理浅析
程序员文章站
2022-03-10 14:31:01
wpf换肤的设计原理,利用资源字典为每种皮肤资源添加不同的样式,在后台切换皮肤资源文件。
截图
上图中,第一张图采用规则样式,第二张图采用不规则样式,截图的时候...
wpf换肤的设计原理,利用资源字典为每种皮肤资源添加不同的样式,在后台切换皮肤资源文件。
截图
上图中,第一张图采用规则样式,第二张图采用不规则样式,截图的时候略有瑕疵。
资源字典
规则样式资源skin.regularstyle.xaml
<resourcedictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <!--window样式--> <style x:key="windowstyle" targettype="window"> <setter property="template"> <setter.value> <controltemplate targettype="window"> <border borderbrush="{templatebinding borderbrush}" borderthickness="{templatebinding borderthickness}"> <border.background> <lineargradientbrush startpoint="0,0" endpoint="0,1"> <gradientstop color="green" offset="0"></gradientstop> <gradientstop color="lightgreen" offset="0.4"></gradientstop> <gradientstop color="white" offset="1"></gradientstop> </lineargradientbrush> </border.background> <contentpresenter></contentpresenter> </border> </controltemplate> </setter.value> </setter> </style> <!--button样式--> <style targettype="button"> <setter property="width" value="70"></setter> <setter property="height" value="23"></setter> <setter property="template"> <setter.value> <controltemplate targettype="button"> <border name="bdr" cursor="arrow" borderbrush="{templatebinding borderbrush}" borderthickness="{templatebinding borderthickness}"> <border.background> <lineargradientbrush startpoint="0,0" endpoint="0,1"> <gradientstop color="white" offset="0"></gradientstop> <gradientstop color="lightgreen" offset="0.3"></gradientstop> <gradientstop color="green" offset="1"></gradientstop> </lineargradientbrush> </border.background> <textblock name="tbk" background="transparent" foreground="darkgreen" textalignment="center" text="{templatebinding content}"></textblock> </border> <controltemplate.triggers> <trigger property="ismouseover" value="true"> <setter targetname="bdr" property="background"> <setter.value> <lineargradientbrush startpoint="0,0" endpoint="0,1"> <gradientstop color="lightgreen" offset="0"></gradientstop> <gradientstop color="green" offset="1"></gradientstop> </lineargradientbrush> </setter.value> </setter> <setter targetname="tbk" property="foreground" value="white"></setter> </trigger> </controltemplate.triggers> </controltemplate> </setter.value> </setter> </style> <!--textbox样式--> <style targettype="textbox"> <setter property="fontfamily" value="sketchflow print"/> <setter property="fontsize" value="14"/> <setter property="template"> <setter.value> <controltemplate targettype="textbox"> <border borderbrush="darkgreen" borderthickness="0.5"> <scrollviewer x:name="part_contenthost" focusable="false" horizontalscrollbarvisibility="hidden" verticalscrollbarvisibility="hidden"></scrollviewer> </border> </controltemplate> </setter.value> </setter> </style> <!--contextmenu样式--> <style targettype="contextmenu"> <setter property="template"> <setter.value> <controltemplate targettype="contextmenu"> <border borderbrush="green" borderthickness="1"> <itemspresenter/> </border> </controltemplate> </setter.value> </setter> </style> <!--menuitem样式--> <style targettype="menuitem"> <setter property="template"> <setter.value> <controltemplate targettype="menuitem"> <border name="border" background="lightgreen" borderthickness="0"> <textblock name="tbk" background="transparent" padding="5,5" text="{templatebinding header}"></textblock> </border> <controltemplate.triggers> <trigger property="ismouseover" value="true"> <setter targetname="border" property="background" value="green"></setter> <setter targetname="tbk" property="foreground" value="white"></setter> </trigger> </controltemplate.triggers> </controltemplate> </setter.value> </setter> </style> <!--textblock样式--> <style targettype="textblock"> <setter property="fontfamily" value="sketchflow print"/> <setter property="fontsize" value="14"/> </style> </resourcedictionary> 不规则样式资源skin.roundedcornerstyle.xaml <resourcedictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <!--window样式--> <style x:key="windowstyle" targettype="window"> <setter property="template"> <setter.value> <controltemplate targettype="window"> <grid margin="10"> <rectangle fill="{dynamicresource {x:static systemcolors.windowbrushkey}}" radiusx="5" radiusy="5"> <rectangle.effect> <dropshadoweffect blurradius="10" color="black" direction="0" opacity="0.8" renderingbias="performance" shadowdepth="0"/> </rectangle.effect> </rectangle> <border borderbrush="{templatebinding borderbrush}" borderthickness="{templatebinding borderthickness}" snapstodevicepixels="true" cornerradius="5"> <border.background> <lineargradientbrush startpoint="0,0" endpoint="0,1"> <gradientstop color="blue" offset="0"></gradientstop> <gradientstop color="lightblue" offset="0.4"></gradientstop> <gradientstop color="white" offset="1"></gradientstop> </lineargradientbrush> </border.background> <contentpresenter></contentpresenter> </border> </grid> </controltemplate> </setter.value> </setter> </style> <!--button样式--> <style targettype="button"> <setter property="width" value="70"></setter> <setter property="height" value="23"></setter> <setter property="template"> <setter.value> <controltemplate targettype="button"> <border name="bdr" cornerradius="5" cursor="hand" borderbrush="{templatebinding borderbrush}" borderthickness="{templatebinding borderthickness}"> <textblock name="tbk" background="transparent" foreground="yellow" textalignment="center" text="{binding relativesource={relativesource templatedparent},path=content}"></textblock> <border.background> <lineargradientbrush startpoint="0,0" endpoint="0,1"> <gradientstop color="white" offset="0"></gradientstop> <gradientstop color="lightblue" offset="0.3"></gradientstop> <gradientstop color="blue" offset="1"></gradientstop> </lineargradientbrush> </border.background> </border> <controltemplate.triggers> <trigger property="ismouseover" value="true"> <setter targetname="bdr" property="background"> <setter.value> <lineargradientbrush startpoint="0,0" endpoint="0,1"> <gradientstop color="lightblue" offset="0"></gradientstop> <gradientstop color="blue" offset="1"></gradientstop> </lineargradientbrush> </setter.value> </setter> <setter targetname="tbk" property="foreground" value="lightyellow"></setter> </trigger> </controltemplate.triggers> </controltemplate> </setter.value> </setter> </style> <!--textbox样式--> <style targettype="textbox"> <setter property="fontfamily" value="times new roman"></setter> <setter property="fontsize" value="14"></setter> <setter property="template"> <setter.value> <controltemplate targettype="textbox"> <border borderbrush="blue" borderthickness="0.5" cornerradius="5"> <scrollviewer x:name="part_contenthost" focusable="false" horizontalscrollbarvisibility="hidden" verticalscrollbarvisibility="hidden"></scrollviewer> </border> </controltemplate> </setter.value> </setter> </style> <!--contextmenu样式--> <style targettype="contextmenu"> <setter property="template"> <setter.value> <controltemplate targettype="contextmenu"> <border cornerradius="5" borderbrush="blue" borderthickness="1"> <itemspresenter/> </border> </controltemplate> </setter.value> </setter> </style> <!--menuitem样式--> <style targettype="menuitem"> <setter property="template"> <setter.value> <controltemplate targettype="menuitem"> <border name="border" background="lightskyblue" borderthickness="0" cornerradius="5"> <textblock name="tbk" background="transparent" padding="5,5" text="{templatebinding header}"></textblock> </border> <controltemplate.triggers> <trigger property="ismouseover" value="true"> <setter targetname="border" property="background" value="blueviolet"></setter> <setter targetname="tbk" property="foreground" value="white"></setter> </trigger> </controltemplate.triggers> </controltemplate> </setter.value> </setter> </style> <!--textblock样式--> <style targettype="textblock"> <setter property="fontfamily" value="times new roman"/> <setter property="fontsize" value="14"/> </style> </resourcedictionary>
仔细观察上面定义的样式,你会发现在定义window样式的时候指定了key,其他的control样式却没有指定key。大家都知道,如果没有给style指定key,那么这个style会应用到所有目标类型(targettype)为指定类型的control。请看下面一段文字:
因为在换肤的过程中,需要动态加载window的样式,所以用dynamicresource作绑定style="{dynamicresource windowstyle}"。
app.xaml
程序运行的时候,默认加载规则样式的皮肤。
<application.resources> <resourcedictionary> <resourcedictionary.mergeddictionaries> <resourcedictionary source="dictionary\skin.regularstyle.xaml"></resourcedictionary> </resourcedictionary.mergeddictionaries> </resourcedictionary> </application.resources>
后台代码
/// <summary> /// menuitem的执行方法 /// </summary> /// <param name="parameter"></param> private void relaymenuitemevent(object parameter) { if (parameter.tostring() == regularstyle) { changeskinresource(skins[0]); } else if (parameter.tostring() == roundedcornerstyle) { changeskinresource(skins[1]); } } /// <summary> /// 更换皮肤资源 /// </summary> /// <param name="skin"></param> private void changeskinresource(resourcedictionary skin) { if (application.current.resources.mergeddictionaries[0].source.isabsoluteuri) { if (application.current.resources.mergeddictionaries[0].source.originalstring != skin.source.originalstring) { application.current.resources.mergeddictionaries[0] = skin; } } else { if (application.current.resources.mergeddictionaries[0].source.originalstring.tostring('\\') != skin.source.originalstring.tostring('/')) { application.current.resources.mergeddictionaries[0] = skin; } } }
运行的时候在mainwindow上右键选择皮肤样式,就可以换肤了。
源码下载:http://xiazai.jb51.net/201610/yuanma/wpfskin(jb51.net).rar
链接:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读