前段时间国外的大牛为Silverlight2定义了四套皮肤,效果让人称奇,美中不足的是四个皮肤不能动态切换,
所以我借花献佛将这四套皮肤放在一起实现了动态切换也就是换肤的效果。
开发平台:VS2008 + Silverlight2
Live Demo
效果图:
选择Bubbly皮肤

选择Flat皮肤

选择Red皮肤

选择Rough皮肤

实现技术主要是利用两个小技巧,
首先是ResourceDictionary,ResourceDictionary中文译做资源字典,顾名思义,就是一个用来存放资源的集合。
ResourceDictionary元素中可以直接嵌入资源,在资源文件里定义ControlTemplate,因为所有的皮肤其实呈现的都是同样的控件,
所以将所有的控件写在里面便于实现元素的重用,然后所有控件的Style属性都和相应的Style动态绑定。

资源文件
1
<ResourceDictionary
2
xmlns="http://schemas.microsoft.com/client/2007"
3
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4
xmlns:controls="clr-namespace:Skinnable;assembly=Skinnable"
5
xmlns:d="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data">
6
7
<Style TargetType="controls:BasicSkin">
8
<Setter Property="Width" Value="1000" />
9
<Setter Property="Height" Value="800" />
10
<Setter Property="Foreground">
11
<Setter.Value>
12
<SolidColorBrush Color="#FFAF17" />
13
</Setter.Value>
14
</Setter>
15
<Setter Property="ButtonStyle" Value="{StaticResource BubblyButtonStyle}" />
16
<Setter Property="ToggleStyle" Value="{StaticResource BubblyToggleStyle}" />
17
<Setter Property="ToolTipStyle" Value="{StaticResource BubblyToolTipStyle}" />
18
<Setter Property="CheckBoxStyle" Value="{StaticResource BubblyCheckBoxStyle}" />
19
<Setter Property="RadioStyle" Value="{StaticResource BubblyRadioStyle}" />
20
<Setter Property="TextBoxStyle" Value="{StaticResource BubblyTextBoxStyle}" />
21
<Setter Property="CalendarStyle" Value="{StaticResource BubblyCalendarStyle}" />
22
<Setter Property="DayButtonStyle" Value="{StaticResource BubblyDayButtonStyle}" />
23
<Setter Property="MonthButtonStyle" Value="{StaticResource BubblyMonthButtonStyle}" />
24
<Setter Property="DatePickerStyle" Value="{StaticResource BubblyDatePickerStyle}" />
25
<Setter Property="LinkStyle" Value="{StaticResource BubblyLinkStyle}" />
26
<Setter Property="DataGridStyle" Value="{StaticResource BubblyDataGridStyle}" />
27
<Setter Property="ColumnHeaderStyle" Value="{StaticResource BubblyColumnHeaderStyle}" />
28
<Setter Property="RowHeaderStyle" Value="{StaticResource BubblyRowHeaderStyle}" />
29
<Setter Property="RowStyle" Value="{StaticResource BubblyRowStyle}" />
30
31
<Setter Property="Template">
32
<Setter.Value>
33
<ControlTemplate TargetType="controls:BasicSkin">
34
<Grid>
35
<Grid Background="#FFE0E4C1">
36
<Grid.ColumnDefinitions>
37
<ColumnDefinition Width="5*"/>
38
<ColumnDefinition Width="20*"/>
39
<ColumnDefinition Width="5*"/>
40
<ColumnDefinition Width="30*"/>
41
<ColumnDefinition Width="30*"/>
42
<ColumnDefinition Width="5*"/>
43
<ColumnDefinition Width="5*"/>
44
</Grid.ColumnDefinitions>
45
<Grid.RowDefinitions>
46
<RowDefinition Height="5*"/>
47
<RowDefinition Height="10*"/>
48
<RowDefinition Height="10*"/>
49
<RowDefinition Height="14*"/>
50
<RowDefinition Height="14*"/>
51
<RowDefinition Height="10*"/>
52
<RowDefinition Height="10*"/>
53
<RowDefinition Height="22*"/>
54
<RowDefinition Height="5*"/>
55
</Grid.RowDefinitions>
56
57
<Button Grid.Column="1" Grid.Row="1" Margin="2" Height="27" Width="79" Content="Button" Style="{TemplateBinding ButtonStyle}">
58
<Button.ToolTip>
59
<ToolTip Content="Button tooltip" Style="{TemplateBinding ToolTipStyle}"/>
60
</Button.ToolTip>
61
</Button>
62
63
<ToggleButton Grid.Column="1" Grid.Row="2" Margin="5" Height="26" Width="65" Content="toggle" Style="{TemplateBinding ToggleStyle}">
64
<ToggleButton.ToolTip>
65
<ToolTip Content="toggle tooltip" Style="{TemplateBinding ToolTipStyle}"/>
66
</ToggleButton.ToolTip>
67
</ToggleButton>
68
69
<Grid Grid.Column="1" Grid.Row="3">
70
<Grid.RowDefinitions>
71
<RowDefinition Height="10*"/>
72
<RowDefinition Height="20*"/>
73
<RowDefinition Height="20*"/>
74
<RowDefinition Height="20*"/>
75
<RowDefinition Height="20*"/>
76
<RowDefinition Height="10*"/>
77
</Grid.RowDefinitions>
78
79
<CheckBox Content="Checkbox One" Grid.Row="1" IsThreeState="True" Style="{TemplateBinding CheckBoxStyle}"/>
80
<CheckBox Content="Checkbox Two" Grid.Row="2" IsThreeState="True" Style="{TemplateBinding CheckBoxStyle}"/>
81
<CheckBox Content="Checkbox Three" Grid.Row="3" IsThreeState="True" Style="{TemplateBinding CheckBoxStyle}"/>
82
</Grid>
83
84
<Grid Grid.Column="1" Grid.Row="4">
85
<Grid.RowDefinitions>
86
<RowDefinition Height="10*"/>
87
<RowDefinition Height="20*"/>
88
<RowDefinition Height="20*"/>
89
<RowDefinition Height="20*"/>
90
<RowDefinition Height="20*"/>
91
<RowDefinition Height="10*"/>
92
</Grid.RowDefinitions>
93
94
<RadioButton Content="Radio One" Grid.Row="1" Style="{TemplateBinding RadioStyle}" GroupName="a"/>
95
<RadioButton Content="Radio Two" Grid.Row="2" Style="{TemplateBinding RadioStyle}" GroupName="a"/>
96
</Grid>
97
98
<TextBox Grid.Column="1" Grid.Row="5" Width="150" Style="{TemplateBinding TextBoxStyle}"/>
99
100
<Calendar Grid.Column="3" Grid.Row="1" Grid.RowSpan="3" Style="{TemplateBinding CalendarStyle}" DayStyle="{TemplateBinding DayButtonStyle}"
101
MonthStyle="{TemplateBinding MonthButtonStyle}" />
102
103
<DatePicker Grid.Column="3" Grid.Row="4" Grid.RowSpan="3" Margin="10" Style="{TemplateBinding DatePickerStyle}" CalendarStyle="{TemplateBinding CalendarStyle}"/>
104
105
<Grid Grid.Column="1" Grid.Row="6">
106
<Grid.ColumnDefinitions>
107
<ColumnDefinition Width="Auto"/>
108
<ColumnDefinition Width="Auto"/>
109
<ColumnDefinition Width="*"/>
110
</Grid.ColumnDefinitions>
111
<TextBlock Grid.Column="0" Text="This is a " Foreground="#FF1E2B33" FontFamily="Trebuchet MS" FontSize="10.5"/>
112
<HyperlinkButton Grid.Column="1" Content="hyperlink" FontFamily="Trebuchet MS" Style="{TemplateBinding LinkStyle}"/>
113
</Grid>
114
115
<Grid Grid.Column="4" Grid.Row="1" Grid.RowSpan="6" Grid.ColumnSpan="3" Margin="30">
116
<d:DataGrid x:Name="dataGridInstance"
117
Style="{TemplateBinding DataGridStyle}"
118
ColumnHeaderStyle="{TemplateBinding ColumnHeaderStyle}"
119
RowHeaderStyle="{TemplateBinding RowHeaderStyle}"
120
RowStyle="{TemplateBinding RowStyle}"
121
AutoGenerateColumns="True"
122
GridlinesVisibility="Horizontal"
123
HeadersVisibility="All"
124
ColumnHeadersHeight="30">
125
<d:DataGrid.ItemsSource>
126
<controls:CustomerList />
127
</d:DataGrid.ItemsSource>
128
</d:DataGrid>
129
</Grid>
130
131
</Grid>
132
</Grid>
133
</ControlTemplate>
134
</Setter.Value>
135
</Setter>
136
</Style>
137
138
</ResourceDictionary>
139
保存这个资源文件为generic.xaml并设置为嵌入式资源。通过删除Custom Tool属性值并设置Build Action为Resource。
这样就可以动态的定义样式和资源文件里的控件模板绑定了。

下面说一说动态定义样式的小技巧,那就是依赖属性(DependencyProperty),它其实是WPF的核心技术点之一,和DependencyObject配合,
提供了WPF中基本的数据存储、访问和通知的机制,具体可参见MSDN上的解说DependencyProperty ,
这篇博客也说的不错WPF中如何实现数据与表示分离。

属性绑定
1
public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register("Foreground", typeof(Brush), typeof(BasicSkin), null);
2
public static readonly DependencyProperty ButtonStyleProperty = DependencyProperty.Register("ButtonStyle", typeof(Style), typeof(BasicSkin), null);
3
public static readonly DependencyProperty ToggleStyleProperty = DependencyProperty.Register("ToggleStyle", typeof(Style), typeof(BasicSkin), null);
4
public static readonly DependencyProperty ToolTipStyleProperty = DependencyProperty.Register("ToolTipStyle", typeof(Style), typeof(BasicSkin), null);
5
public static readonly DependencyProperty CheckBoxStyleProperty = DependencyProperty.Register("CheckBoxStyle", typeof(Style), typeof(BasicSkin), null);
6
public static readonly DependencyProperty RadioStyleProperty = DependencyProperty.Register("RadioStyle", typeof(Style), typeof(BasicSkin), null);
7
public static readonly DependencyProperty TextBoxStyleProperty = DependencyProperty.Register("TextBoxStyle", typeof(Style), typeof(BasicSkin), null);
8
public static readonly DependencyProperty CalendarStyleProperty = DependencyProperty.Register("CalendarStyle", typeof(Style), typeof(BasicSkin), null);
9
public static readonly DependencyProperty DayButtonStyleProperty = DependencyProperty.Register("DayButtonStyle", typeof(Style), typeof(BasicSkin), null);
10
public static readonly DependencyProperty MonthButtonStyleProperty = DependencyProperty.Register("MonthButtonStyle", typeof(Style), typeof(BasicSkin), null);
11
public static readonly DependencyProperty DatePickerStyleProperty = DependencyProperty.Register("DatePickerStyle", typeof(Style), typeof(BasicSkin), null);
12
public static readonly DependencyProperty LinkStyleProperty = DependencyProperty.Register("LinkStyle", typeof(Style), typeof(BasicSkin), null);
13
public static readonly DependencyProperty DataGridStyleProperty = DependencyProperty.Register("DataGridStyle", typeof(Style), typeof(BasicSkin), null);
14
public static readonly DependencyProperty ColumnHeaderStyleProperty = DependencyProperty.Register("ColumnHeaderStyle", typeof(Style), typeof(BasicSkin), null);
15
public static readonly DependencyProperty RowHeaderStyleProperty = DependencyProperty.Register("RowHeaderStyle", typeof(Style), typeof(BasicSkin), null);
16
public static readonly DependencyProperty RowStyleProperty = DependencyProperty.Register("RowStyle", typeof(Style), typeof(BasicSkin), null);
17
18
19
/**//// <summary>
20
/// Expose our background
21
/// </summary>
22
public Brush Foreground
23
{
24
get
{ return (Brush)GetValue(ForegroundProperty); }
25
set
{ SetValue(ForegroundProperty, value); }
26
}
27
28
/**//// <summary>
29
/// Expose our button style
30
/// </summary>
31
public Style ButtonStyle
32
{
33
get
{ return (Style)GetValue(ButtonStyleProperty); }
34
set
{ SetValue(ButtonStyleProperty, value); }
35
}
36
37
![]()