当前位置: 移动技术网 > IT编程>开发语言>c# > WPF换肤设计原理浅析

WPF换肤设计原理浅析

2019年07月18日  | 移动技术网IT编程  | 我要评论
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上右键选择皮肤样式,就可以换肤了。

源码下载:

链接:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网