转载

WPF之换肤

WPF之换肤

设计原理

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

截图

WPF之换肤

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

资源字典

规则样式资源Skin.RegularStyle.xaml

WPF之换肤
  1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"   2                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">   3    4     <!--Window样式-->   5     <Style x:Key="WindowStyle" TargetType="Window">   6         <Setter Property="Template">   7             <Setter.Value>   8                 <ControlTemplate TargetType="Window">   9                     <Border BorderBrush="{TemplateBinding BorderBrush}"   10                             BorderThickness="{TemplateBinding BorderThickness}">  11                         <Border.Background>  12                             <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">  13                                 <GradientStop Color="Green" Offset="0"></GradientStop>  14                                 <GradientStop Color="LightGreen" Offset="0.4"></GradientStop>  15                                 <GradientStop Color="White" Offset="1"></GradientStop>  16                             </LinearGradientBrush>  17                         </Border.Background>  18                         <ContentPresenter></ContentPresenter>  19                     </Border>  20                 </ControlTemplate>  21             </Setter.Value>  22         </Setter>  23     </Style>  24   25     <!--Button样式-->  26     <Style TargetType="Button">  27         <Setter Property="Width" Value="70"></Setter>  28         <Setter Property="Height" Value="23"></Setter>  29         <Setter Property="Template">  30             <Setter.Value>  31                 <ControlTemplate TargetType="Button">  32                     <Border Name="bdr" Cursor="Arrow"  33                             BorderBrush="{TemplateBinding BorderBrush}"   34                             BorderThickness="{TemplateBinding BorderThickness}">  35                         <Border.Background>  36                             <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">  37                                 <GradientStop Color="White" Offset="0"></GradientStop>  38                                 <GradientStop Color="LightGreen" Offset="0.3"></GradientStop>  39                                 <GradientStop Color="Green" Offset="1"></GradientStop>  40                             </LinearGradientBrush>  41                         </Border.Background>  42                         <TextBlock Name="tbk" Background="Transparent" Foreground="DarkGreen" TextAlignment="Center"  43                                    Text="{TemplateBinding Content}"></TextBlock>  44                     </Border>  45                     <ControlTemplate.Triggers>  46                         <Trigger Property="IsMouseOver" Value="True">  47                             <Setter TargetName="bdr" Property="Background">  48                                 <Setter.Value>  49                                     <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">  50                                         <GradientStop Color="LightGreen" Offset="0"></GradientStop>  51                                         <GradientStop Color="Green" Offset="1"></GradientStop>  52                                     </LinearGradientBrush>  53                                 </Setter.Value>  54                             </Setter>  55                             <Setter TargetName="tbk" Property="Foreground" Value="White"></Setter>  56                         </Trigger>  57                     </ControlTemplate.Triggers>  58                 </ControlTemplate>  59             </Setter.Value>  60         </Setter>  61     </Style>  62   63     <!--TextBox样式-->  64     <Style TargetType="TextBox">  65         <Setter Property="FontFamily" Value="SketchFlow Print"/>  66         <Setter Property="FontSize" Value="14"/>  67         <Setter Property="Template">  68             <Setter.Value>  69                 <ControlTemplate TargetType="TextBox">  70                     <Border BorderBrush="DarkGreen" BorderThickness="0.5">  71                         <ScrollViewer x:Name="PART_ContentHost" Focusable="false"   72                                       HorizontalScrollBarVisibility="Hidden"   73                                       VerticalScrollBarVisibility="Hidden"></ScrollViewer>  74                     </Border>  75                 </ControlTemplate>  76             </Setter.Value>  77         </Setter>  78     </Style>  79   80     <!--ContextMenu样式-->  81     <Style TargetType="ContextMenu">  82         <Setter Property="Template">  83             <Setter.Value>  84                 <ControlTemplate TargetType="ContextMenu">  85                     <Border BorderBrush="Green" BorderThickness="1">  86                         <ItemsPresenter/>  87                     </Border>  88                 </ControlTemplate>  89             </Setter.Value>  90         </Setter>  91     </Style>  92   93     <!--MenuItem样式-->  94     <Style TargetType="MenuItem">  95         <Setter Property="Template">  96             <Setter.Value>  97                 <ControlTemplate TargetType="MenuItem">  98                     <Border Name="border" Background="LightGreen" BorderThickness="0">  99                         <TextBlock Name="tbk" Background="Transparent" Padding="5,5" 100                                    Text="{TemplateBinding Header}"></TextBlock> 101                     </Border> 102                     <ControlTemplate.Triggers> 103                         <Trigger Property="IsMouseOver" Value="True"> 104                             <Setter TargetName="border" Property="Background" Value="Green"></Setter> 105                             <Setter TargetName="tbk" Property="Foreground" Value="White"></Setter> 106                         </Trigger> 107                     </ControlTemplate.Triggers> 108                 </ControlTemplate> 109             </Setter.Value> 110         </Setter> 111     </Style> 112  113     <!--TextBlock样式--> 114     <Style TargetType="TextBlock"> 115         <Setter Property="FontFamily" Value="SketchFlow Print"/> 116         <Setter Property="FontSize" Value="14"/> 117     </Style> 118  119 </ResourceDictionary>
View Code

不规则样式资源Skin.RoundedCornerStyle.xaml

WPF之换肤
  1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"   2                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">   3    4     <!--Window样式-->   5     <Style x:Key="WindowStyle" TargetType="Window">   6         <Setter Property="Template">   7             <Setter.Value>   8                 <ControlTemplate TargetType="Window">   9                     <Grid Margin="10">  10                         <Rectangle Fill="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"    11                                    RadiusX="5" RadiusY="5">  12                             <Rectangle.Effect>  13                                 <DropShadowEffect BlurRadius="10" Color="Black" Direction="0" Opacity="0.8"  14                                                   RenderingBias="Performance" ShadowDepth="0"/>  15                             </Rectangle.Effect>  16                         </Rectangle>  17                         <Border BorderBrush="{TemplateBinding BorderBrush}"    18                                 BorderThickness="{TemplateBinding BorderThickness}"   19                                 SnapsToDevicePixels="True" CornerRadius="5">  20                             <Border.Background>  21                                 <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">  22                                     <GradientStop Color="Blue" Offset="0"></GradientStop>  23                                     <GradientStop Color="LightBlue" Offset="0.4"></GradientStop>  24                                     <GradientStop Color="White" Offset="1"></GradientStop>  25                                 </LinearGradientBrush>  26                             </Border.Background>  27                             <ContentPresenter></ContentPresenter>  28                         </Border>  29                     </Grid>  30                 </ControlTemplate>  31             </Setter.Value>  32         </Setter>  33     </Style>  34       35     <!--Button样式-->  36     <Style TargetType="Button">  37         <Setter Property="Width" Value="70"></Setter>  38         <Setter Property="Height" Value="23"></Setter>  39         <Setter Property="Template">  40             <Setter.Value>  41                 <ControlTemplate TargetType="Button">  42                     <Border Name="bdr" CornerRadius="5" Cursor="Hand"  43                             BorderBrush="{TemplateBinding BorderBrush}"    44                             BorderThickness="{TemplateBinding BorderThickness}">  45                         <TextBlock Name="tbk" Background="Transparent" Foreground="Yellow"  TextAlignment="Center"  46                                    Text="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Content}"></TextBlock>  47                         <Border.Background>  48                             <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">  49                                 <GradientStop Color="White" Offset="0"></GradientStop>  50                                 <GradientStop Color="LightBlue" Offset="0.3"></GradientStop>  51                                 <GradientStop Color="Blue" Offset="1"></GradientStop>  52                             </LinearGradientBrush>  53                         </Border.Background>  54                     </Border>  55                     <ControlTemplate.Triggers>  56                         <Trigger Property="IsMouseOver" Value="True">  57                             <Setter TargetName="bdr" Property="Background">  58                                 <Setter.Value>  59                                     <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">  60                                         <GradientStop Color="LightBlue" Offset="0"></GradientStop>  61                                         <GradientStop Color="Blue" Offset="1"></GradientStop>  62                                     </LinearGradientBrush>  63                                 </Setter.Value>  64                             </Setter>  65                             <Setter TargetName="tbk" Property="Foreground" Value="LightYellow"></Setter>  66                         </Trigger>  67                     </ControlTemplate.Triggers>  68                 </ControlTemplate>  69             </Setter.Value>  70         </Setter>  71     </Style>  72   73     <!--TextBox样式-->  74     <Style TargetType="TextBox">  75         <Setter Property="FontFamily" Value="Times New Roman"></Setter>  76         <Setter Property="FontSize" Value="14"></Setter>  77         <Setter Property="Template">  78             <Setter.Value>  79                 <ControlTemplate TargetType="TextBox">  80                     <Border BorderBrush="Blue" BorderThickness="0.5" CornerRadius="5">  81                         <ScrollViewer x:Name="PART_ContentHost" Focusable="false"   82                                       HorizontalScrollBarVisibility="Hidden"   83                                       VerticalScrollBarVisibility="Hidden"></ScrollViewer>  84                     </Border>  85                 </ControlTemplate>  86             </Setter.Value>  87         </Setter>  88     </Style>  89   90     <!--ContextMenu样式-->  91     <Style TargetType="ContextMenu">  92         <Setter Property="Template">  93             <Setter.Value>  94                 <ControlTemplate TargetType="ContextMenu">  95                     <Border CornerRadius="5" BorderBrush="Blue" BorderThickness="1">  96                         <ItemsPresenter/>  97                     </Border>  98                 </ControlTemplate>  99             </Setter.Value> 100         </Setter> 101     </Style> 102  103     <!--MenuItem样式--> 104     <Style TargetType="MenuItem"> 105         <Setter Property="Template"> 106             <Setter.Value> 107                 <ControlTemplate TargetType="MenuItem"> 108                     <Border Name="border" Background="LightSkyBlue" BorderThickness="0" CornerRadius="5"> 109                         <TextBlock Name="tbk" Background="Transparent" Padding="5,5" 110                                    Text="{TemplateBinding Header}"></TextBlock> 111                     </Border> 112                     <ControlTemplate.Triggers> 113                         <Trigger Property="IsMouseOver" Value="True"> 114                             <Setter TargetName="border" Property="Background" Value="BlueViolet"></Setter> 115                             <Setter TargetName="tbk" Property="Foreground" Value="White"></Setter> 116                         </Trigger> 117                     </ControlTemplate.Triggers> 118                 </ControlTemplate> 119             </Setter.Value> 120         </Setter> 121     </Style> 122      123     <!--TextBlock样式--> 124     <Style TargetType="TextBlock"> 125         <Setter Property="FontFamily" Value="Times New Roman"/> 126         <Setter Property="FontSize" Value="14"/> 127     </Style> 128 </ResourceDictionary>
View Code

仔细观察上面定义的样式,你会发现在定义Window样式的时候指定了Key,其他的Control样式却没有指定Key。大家都知道,如果没有给Style指定Key,那么这个Style会应用到所有目标类型(TargetType)为指定类型的Control。请看下面一段文字:

WPF之换肤

因为在换肤的过程中,需要动态加载Window的样式,所以用DynamicResource作绑定Style="{DynamicResource WindowStyle}"。

App.xaml

程序运行的时候,默认加载规则样式的皮肤。

WPF之换肤
1     <Application.Resources> 2         <ResourceDictionary> 3             <ResourceDictionary.MergedDictionaries> 4                 <ResourceDictionary Source="Dictionary/Skin.RegularStyle.xaml"></ResourceDictionary> 5             </ResourceDictionary.MergedDictionaries> 6         </ResourceDictionary> 7     </Application.Resources>
View Code

后台代码

WPF之换肤
 1         /// <summary>  2         /// MenuItem的执行方法  3         /// </summary>  4         /// <param name="parameter"></param>  5         private void RelayMenuItemEvent(object parameter)  6         {  7             if (parameter.ToString() == RegularStyle)  8             {  9                 ChangeSkinResource(Skins[0]); 10             } 11             else if (parameter.ToString() == RoundedCornerStyle) 12             { 13                 ChangeSkinResource(Skins[1]); 14             } 15         } 16  17         /// <summary> 18         /// 更换皮肤资源 19         /// </summary> 20         /// <param name="skin"></param> 21         private void ChangeSkinResource(ResourceDictionary skin) 22         { 23             if (Application.Current.Resources.MergedDictionaries[0].Source.IsAbsoluteUri) 24             { 25                 if (Application.Current.Resources.MergedDictionaries[0].Source.OriginalString != skin.Source.OriginalString) 26                 { 27                     Application.Current.Resources.MergedDictionaries[0] = skin; 28                 } 29             } 30             else 31             { 32                 if (Application.Current.Resources.MergedDictionaries[0].Source.OriginalString.ToString('//') != skin.Source.OriginalString.ToString('/')) 33                 { 34                     Application.Current.Resources.MergedDictionaries[0] = skin; 35                 } 36             } 37         }
View Code

运行的时候在MainWindow上右键选择皮肤样式,就可以换肤了。

源码下载

链接

stackoverflow

正文到此结束
Loading...