WPF换肤设计原理浅析_C#教程

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

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

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索wpf
换肤
wpf换肤、wpf 动态换肤、果酸换肤原理、果酸换肤的原理、lol内存换肤原理,以便于您获取更多的相关知识。

时间: 2024-10-24 14:41:03

WPF换肤设计原理浅析_C#教程的相关文章

WPF换肤之四:界面设计和代码设计分离

原文:WPF换肤之四:界面设计和代码设计分离 说起WPF来,除了总所周知的图形处理核心的变化外,和Winform比起来,还有一个巨大的变革,那就是真正意义上做到了界面设计和代码设计的分离.这样可以让美工和程序分开进行,而不是糅合在一块,这样做的好处当然也是显而易见的:提高了开发效率. 原先的设计方式 在我们之前设计的代码中,每当添加一个新的窗体的时候,我总是会在这个新的窗体的XAML文件中加入如下的代码,以便使样式能够应用上去: View Code <Window x:Class="Wpf

WPF换肤之六:酷炫的时区浏览小精灵

原文:WPF换肤之六:酷炫的时区浏览小精灵 由于工作需要,经常要查看到不同地区的 当前时间,以前总是对照着时区表来进行加减运算,现在有了这个小工具以后,感觉省心了不少.下面是软件的截图: 效果图赏析   在界面上,有能够冉冉升起的太阳或者月亮,有缓慢飘动的浮云,有青葱翠绿的花叶, 当然,也有显目的时区显示.如果要是放在WinForm时代,要实现这样的界面,真的是繁琐和复杂,但是在WPF中,利用XAML控制前台界面,利用CodeBehind控制窗口拖动,日月变换等等逻辑,真的是简便而且效果强大.其

WPF换肤之一:创建圆角窗体

原文:WPF换肤之一:创建圆角窗体     我们都期望自己的软件能够有一套看上去很吸引人眼球的外衣,使得别人看上去既专业又有美感.这个系列就带领着大家一步一步的讲解如何设计出一套自己的WPF的窗体皮肤,如果文中有任何错误或者不足,还请指出.     WPF是微软大战略中的一个重心所在,学习WPF可谓是一举多得:首先,学习WPF可以让你了解SilverLight的80%:其次,XAML语言可以让你快速的入手WCF和WF:更甚者,就是WPF给予DX渲染核心,抛弃了传统WINFORM以GDI+为主的渲

WPF换肤之八:创建3D浏览效果

原文:WPF换肤之八:创建3D浏览效果 上节中,我们展示了WPF中的异步以及界面线程交互的方式,使得应用程序的显示更加的流畅.这节我们主要讲解如何设计一个具有3D浏览效果的天气信息浏览器. 效果显示 下面我们看截图: 是不是能够感受到一种与众不同的感觉.如果你能够感受到它的与众不同,这也是我本节所要达到的目标. 实现方式 上面的只是一个简单的3D图形,它的产生需要依赖于WPF中的MeshGeometry3D对象,这个对象按照微软官方的解释就是用于生成3D形状的三角形基元,它有三个比较重要的属性:

WPF换肤之二:可拉动的窗体

原文:WPF换肤之二:可拉动的窗体 让我们接着上一章: WPF换肤之一:创建圆角窗体 来继续. 在这一章,我主要是实现对圆角窗体的拖动,改变大小功能. 拖动自绘窗体的步骤 首先,通过上节的设计,我们知道了如何设计一个圆角窗体,通过XAML代码量,我们发现设置这个窗体是多么的简单.但是如何让窗体能够进行Resize呢? 在Winform时代,我们通过WndProc(ref Message m)处理窗体界面消息来实现,那么在WPF中是否也是如此呢? 其实在WPF中,虽说封装比较紧密,但是对于处理界面

WPF换肤之七:异步

原文:WPF换肤之七:异步 在WinForm时代,相信大家都遇到过这种情形,如果在程序设计过程中遇到了耗时的操作,不使用异步会导致程序假死.当然,在WPF中,这种情况也是存在的,所以我们就需要寻找一种解决方法来让程序界面响应和耗时操作异步进行,那么上述假死的情况就不会发生了. 这一节就着重讲解异步以及线程和界面交互. 异步使用方式(APM模式) 在上节中,我们给一个普通的Window窗口做了换肤处理,呈现出了一个非常酷的时区浏览小工具.当然,这一节,我们还是以那个工具为主,为其增加天气预报功能,

LZW数据压缩算法的原理分析_C#教程

1.LZW的全称是什么? Lempel-Ziv-Welch (LZW). 2. LZW的简介和压缩原理是什么? LZW压缩算法是一种新颖的压缩方法,由Lemple-Ziv-Welch 三人共同创造,用他们的名字命名.它采用了一种先进的串表压缩,将每个第一次出现的串放在一个串表中,用一个数字来表示串,压缩文件只存贮数字,则不存贮串,从而使图象文件的压缩效率得到较大的提高.奇妙的是,不管是在压缩还是在解压缩的过程中都能正确的建立这个串表,压缩或解压缩完成后,这个串表又被丢弃. LZW算法中,首先建立

WPF调用Matlab函数的方法_C#教程

有的时候用C#写图像处理方法,比较费事,不如Matlab简单,但是Matlab又做不出WPF那样的好看界面,怎么办呢. 今天正好我要实现这个功能,就顺便写个小例子,给需要的人做个借鉴. 想要用WPF调用Matlab代码,就用到了Matlab生成.DLL文件的功能. 注:我的VS版本是2013,Matlab版本是2012a,两个软件不算新也不算老,应该是现在普遍用的版本 首先,生成Matlab的.DLL文件 在matlab的左下角选择start-matlab-NE-deploytool,或者直接在

C#权限管理和设计浅谈_C#教程

此文主要想和大家分享的是这段时间,对权限管理和设计的断断续续的思考学习,和个人的一些软件开发等方面的看法. 提到'权限管理和设计',大家可能会第一时间想到这园子里的 吉日嘎拉,在这方面他可以算是'大牛'或专家 --他的'通用权限管理系统',究竟做的怎样,看看他的博客就差不多可以知道了(貌似我在给他做推广,呵呵...,but in fact,is not),别的暂且不敢说,最起码可以看出他研究的比较深入和狂热,其系统也具有一定的'成熟度',用他的话来说--就是在努力做到他的极致.他做的是通用权限管