软件编程
位置:首页>> 软件编程>> C#编程>> WPF换肤设计原理浅析

WPF换肤设计原理浅析

作者:sunny906  发布时间:2022-11-18 00:37:00 

标签:WPF,换肤

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。请看下面一段文字:

WPF换肤设计原理浅析

因为在换肤的过程中,需要动态加载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之家 www.aspxhome.com