好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

WPF换肤设计原理浅析

wpf 换肤 的设计原理,利用资源字典为每种皮肤资源添加不同的样式,在后台切换皮肤资源文件。

截图

上图中,第一张图采用规则样式,第二张图采用不规则样式,截图的时候略有瑕疵。

资源字典

规则样式资源skin.regularstyle.xaml

?

< resourcedictionary xmlns = "http://schemas.microsoft测试数据/winfx/2006/xaml/presentation"

      xmlns:x = "http://schemas.microsoft测试数据/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测试数据/winfx/2006/xaml/presentation"

      xmlns:x = "http://schemas.microsoft测试数据/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上右键选择皮肤样式,就可以换肤了。

源码下载: wpfskin.rar

链接: stackoverflow

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

dy("nrwz");

查看更多关于WPF换肤设计原理浅析的详细内容...

  阅读:46次