你的位置:首页 > ASP.net教程

[ASP.net教程]WPF之换肤


WPF之换肤

设计原理

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

截图

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

资源字典

规则样式资源Skin.RegularStyle.xaml

 1 <ResourceDictionary ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 2           ="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

 1 <ResourceDictionary ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 2           ="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。请看下面一段文字:

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

App.xaml

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

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

后台代码

 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       else31       {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