WPF之动态换肤
如何实现换肤呢,对于复杂的换肤操作,如,更换按钮样式、窗口样式等,我们需要写多个资源字典来表示不同的皮肤,通过动态加载不同的资源字典来实现换肤的效果;对于简单的换肤操作,如更改背景颜色、设置窗体透明度,这种换肤操作,我们就不能使用上面的方法了,这个时候,我们只要在一个全局对象中添加几个属性,如背景颜色、前景颜色、窗体透明度等,然后,再绑定这几个属性就能达到我们想要的效果。
解决方案:动态加载资源字典
1 <Window x:Class="DynamicallySkinnable.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="MainWindow" Height="350" Width="525"> 5 <Window.Resources> 6 </Window.Resources> 7 <Grid> 8 <StackPanel Margin="20" Orientation="Vertical"> 9 <TextBox x:Name="tb" 10 HorizontalAlignment="Center" VerticalAlignment="Center" 11 Text="测试用例"></TextBox> 12 <Button Content="Click Me" 13 Click="Button_Click"> 14 <Button.ContextMenu> 15 <ContextMenu> 16 <MenuItem x:Name="menuBlue" Header="Blue Skin" Click="menuAero_Click"/> 17 <MenuItem x:Name="menuRoyale" Header="Red Skin" Click="menuRoyale_Click"/> 18 <MenuItem x:Name="menuLuna" Header="Black Skin" Click="menuLuna_Click"/> 19 </ContextMenu> 20 </Button.ContextMenu> 21 </Button> 22 23 </StackPanel> 24 </Grid> 25 </Window>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace DynamicallySkinnable { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { Button btn = (Button)e.OriginalSource; btn.ContextMenu.IsOpen = true; } private void menuAero_Click(object sender, RoutedEventArgs e) { /* Application.Current.Resources.MergedDictionaries.Clear(); //清除现有资源 //获取要应用的资源字典 ResourceDictionary resource = (ResourceDictionary)Application.LoadComponent( new Uri("/PresentationFramework.Aero, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35;component/themes/aero.normalcolor.xaml", UriKind.Relative)); //将资源字典合并到当前资源中 Application.Current.Resources.MergedDictionaries.Add(resource); */ //this.Resources.MergedDictionaries.Clear(); ResourceDictionary resource = (ResourceDictionary)Application.LoadComponent(new Uri("/DynamicallySkinnable;component/Skins/BlueSkin.xaml", UriKind.Relative)); this.Resources.MergedDictionaries.Add(resource); } private void menuRoyale_Click(object sender, RoutedEventArgs e) { /* Application.Current.Resources.MergedDictionaries.Clear(); ResourceDictionary resource = (ResourceDictionary)Application.LoadComponent( new Uri("/PresentationFramework.Royale, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35;component/themes/royale.normalcolor.xaml", UriKind.Relative)); Application.Current.Resources.MergedDictionaries.Add(resource); */ //this.Resources.MergedDictionaries.Clear(); ResourceDictionary resource = (ResourceDictionary)Application.LoadComponent(new Uri("/DynamicallySkinnable;component/Skins/RedSkin.xaml", UriKind.Relative)); this.Resources.MergedDictionaries.Add(resource); } private void menuLuna_Click(object sender, RoutedEventArgs e) { /* Application.Current.Resources.MergedDictionaries.Clear(); ResourceDictionary resource = (ResourceDictionary)Application.LoadComponent( new Uri("/PresentationFramework.Luna, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35;component/themes/luna.normalcolor.xaml", UriKind.Relative)); Application.Current.Resources.MergedDictionaries.Add(resource); */ //this.Resources.MergedDictionaries.Clear(); ResourceDictionary resource = (ResourceDictionary)Application.LoadComponent(new Uri("/DynamicallySkinnable;component/Skins/BlackSkin.xaml", UriKind.Relative)); this.Resources.MergedDictionaries.Add(resource); } private void button1_Click(object sender, RoutedEventArgs e) { Button btn = (Button)e.OriginalSource; btn.ContextMenu.IsOpen = true; } } }
后记:
动态换肤在程序里面已经基本实现,主要是资源字典的动态加载,以及背景图片的替换,在Grid.Background的ImageBrush属性里面,在点击按钮之后更换了资源字典之后还是需要手动写代码替换一下背景的
写的时候就在想能不能写成属性通知的那个样子,当它发生改变了,自动去更新,不用我手动的去写代码,但是有种无从下手的感觉。
这段时间老是会觉得自己的知识不够,遇到问题不能从本质上去了解及解决,一定要在网上荡代码参考怎么样的,实用主义,有的时候是好,但是后期的积累问题会越来越难以解决,所以要注意夯实基础,这段时间
需要好好的看一看基础的组成什么的。感觉自己什么都很匮乏。代码写的不够优雅,自己看着都觉得凌乱,变量名不优美,看着不赏心悦目。这些都是我的目标,现在方向有了。向着我的程序员之路,fighting!