天天看點

WPF之動态換膚

原文: 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!

繼續閱讀