在WPF中换肤异常方便,只有将窗口资源设置为不同的ResourceDictionary就可以了。而且可以换得很彻底,甚至是彻底改变整个窗口上控件的种类,大小,个数等。
下面是一个实现。
建立一个叫做Blue.xaml的文件,在上面写入
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<StackPanel x:Key="Root" Height="120">
<Button Background="Blue" Height="40"/>
<Button Background="Blue" Height="40"/>
<Button Background="Blue" Height="40"/>
</StackPanel>
</ResourceDictionary>
然后建立一个叫Green.xaml的文件,在上面写入
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Grid x:Key="Root" Width="170" Height="90">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Button Background="Green" Grid.Column="0" Grid.Row="0"/>
<Button Background="Green" Grid.Column="1" Grid.Row="0"/>
<Button Background="Green" Grid.Column="0" Grid.Row="1"/>
<Button Background="Green" Grid.Column="1" Grid.Row="1"/>
</Grid>
</ResourceDictionary>
然后是主窗口的xaml
<Window x:Class="SkinTest2.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="150" Width="300" Content="{DynamicResource Root}">
</Window>
将窗口的Content设置为一个动态资源Root就行了。
添加一个新类
Blue,在它的构造函数中设置将Blue.xaml中的ResourceDictionary设置给窗口
ResourceDictionary resDic = new ResourceDictionary();
resDic.Source = new Uri("Blue.xaml", UriKind.Relative);
window.Resources = resDic;
StackPanel stackPanel = window.Content as StackPanel;
通过转型来得到Blue中的StackPanel, 这种方法看起来有的粗鲁,但是没有想到别的办法
for (int i = 0; i < stackPanel.Children.Count; i++)
{
button[i] = stackPanel.Children[i] as Button;
button[i].Click += handler[i];
}
遍历stackPanel的子元素,把Button一个个地取出来添加事件。没法子。在写Blue.xaml中的ResourceDictionary的时候不能给资源StackPanel的子元素再设置x:key了
添加一个Green类,同样这么干。
最后测试一下,在主窗口中放入一个托盘按钮,方便一会切换皮肤
private Blue blue;
private Green green;
private System.Windows.Forms.NotifyIcon notifyIcon;
}
public Window1()
{
InitializeComponent();
notifyIcon = new System.Windows.Forms.NotifyIcon();
notifyIcon.Icon = Properties.Resources.icon2;
System.Windows.Forms.ContextMenu contextMenu = new System.Windows.Forms.ContextMenu();
给contextMenu添加两个菜单项
contextMenu.MenuItems.Add("Blue").Click +=
((sender, e) =>
{
if (blue == null)
{
blue = new Blue(this);
green = null;
}
});
contextMenu.MenuItems.Add("green").Click +=
((sender, e) =>
{
if(green == null)
{
green = new Green(this);
blue = null;
}
});
这里用了3.0中的Lambda表达式,看起来还不赖,比起boost中的那个类库级的Lambda看起来自然多了。
notifyIcon.ContextMenu = contextMenu;
notifyIcon.Visible = true;
右击托盘图标,可以任意切换。当然换得这么彻底也很少见,都换了,和新建一个窗口有啥区别: )