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

链接:stackoverflow

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

(0)

相关推荐

  • asp.net简单实现页面换肤的方法

    本文实例讲述了asp.net简单实现页面换肤的方法.分享给大家供大家参考,具体如下: 这里实现页面换肤效果,可以 给html form 添加相应的样式 代码如下: private string _StyleClass; public string StyleClass { get { return _StyleClass; } set { _StyleClass = value; } } private void StyleForm() { HtmlForm Form1 = this.FindC

  • Javascript结合css实现网页换肤功能

    Html代码部分: 1.要有一个带id的样式表链接,我们要通过操作这个链接来调用不同的href. <link href="css/main0.css" rel="stylesheet" type="text/css" id="cssfile" /> 2.皮肤选择按钮(后台为每个li添加onclick事件,触发换肤功能) <ul id="skin"> <li id="s

  • 采用XHTML和CSS设计可重用可换肤的WEB站点的方法第1/4页

    XHTML 标准的目标是取代 html.按照 W3C 的说法,"XHTML 是 html 的继承者"(http://www.w3.org/MarkUp/). XHTML具有两大目标: 在文档结构和表示形式之间创建更明显的分离. 将 html 重新表示为 XML 的应用程序. 使用XHTML标准的好处是:只需设计页面一次,即可让该页以完全相同的方式在任何现代的浏览器中显示和工作.例如,在按照标准生成以后,页面在Internet Explorer.Mozilla Firefox.Netsc

  • javascript实现动态CSS换肤技术的脚本

    <SCRIPT LANGUAGE=javascript>     <!--     function SetCookie(name,value){         var argv=SetCookie.arguments;         var argc=SetCookie.arguments.length;         var expires=(2<argc)?argv[2]:null;         var path=(3<argc)?argv[3]:null; 

  • 使用jQuery实现的网页版的个人简历(可换肤)

    复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title

  • js动态修改整个页面样式达到换肤效果

    jsPro1\js动态修改整个html页面样式(换肤).html 复制代码 代码如下: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>动态修改页面样式

  • 漂亮的widgets,支持换肤和后期开发新皮肤

    作者:ucren演示效果:http://ucren.com/ucren-examples/widgets.html 已知缺陷: 1.换肤功能由于图片变动量比较大,所以加载有些慢. 2.widgets 不支持多态. 未来考虑解决的问题: 1.对图片进行预载处理 2.与框架 vjbox 整合到一起 未来考虑开发的新控件: 1.滑块调节器(类似windows音量调节器) 2.进度条 3.outlook 菜单 4.树 widgets.js 复制代码 代码如下: /*  * Ucren example.

  • js+css简单实现网页换肤效果

    本文实例讲述了js+css简单实现网页换肤效果.分享给大家供大家参考,具体如下: 这里做了3套外观,分别使用不同文件夹下的同名css文件,那么怎样实现js替换加载呢? 3个按钮如下: <a id="skin1" href="javascript:void(0)" class="easyui-linkbutton" onclick="changeCss('default')">蓝色皮肤</a><br

  • JQuery 网站换肤功能实现代码

    从那以后,我找到了很多可以让访客通过鼠标点击某个地方切换样式表的方法.但最近我要写一篇如何 使用jQuery编写简单代码实现它的教程. 我将向你们逐步解说整个的过程,不仅仅因为要展示jQuery代码的简介,同时也要揭示jQuery库中的若干高级特性. 首先,代码 复制代码 代码如下: $(document).ready(function() { $('.styleswitch').click(function() { switchStylestyle(this.getAttribute("rel

  • jQuery之网页换肤实现代码

    下面是代码: 首先HTML页面代码如下: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> &l

随机推荐