Silverlight4中實現Theme的動態切換

雲霏霏發表於2014-09-03

  Silverlight一般用來開發一些企業的應用系統,如果使用者一直面對同一種風格的頁面,時間長了難免厭煩,所以一般都會提供好幾種風格及Theme供使用者選中,下面就來說一下如何在不重新登入系統的情況下,實現風格的動態切換。我們寫一個Demo來說明一下。

  新建一個Silverlight的專案,並新增一個預設的站點,先來寫一下頁面吧,簡單起見,只放兩個控制元件,MainPage的程式碼如下:

<UserControl x:Class="SilverlightChangeTheme.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
      <Button Content="ChangeTheme" Height="23" HorizontalAlignment="Left" 
              Margin="40,66,0,0" Name="button1" VerticalAlignment="Top" 
              Width="108" Click="button1_Click" Style="{StaticResource BtnStyle}" />
      <TextBlock Height="23" HorizontalAlignment="Left" 
                 Margin="58,37,0,0" Name="textBlock1" 
                 Text="文字樣式" VerticalAlignment="Top" 
                 FontSize="14" Width="101" Style="{StaticResource txtStyle}" />
   </Grid>
</UserControl>

效果圖如下:

就是一個簡單的按鈕和一個TextBlock,下面要實現的效果是點選按鈕實現文字和按鈕字型顏色改變(樣式要從資原始檔載入);

那麼既然要實現切換風格,首先要有資原始檔,我們先建兩個Silverlight Resource Dictionary,紅色風格和藍色風格,命名為Blue.xaml和Red.xaml,程式碼如下:

Red.xaml:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

   <Style TargetType="Button" x:Key="BtnStyle">
      <Setter Property="Foreground" Value="Red" />
   </Style>
   <Style TargetType="TextBlock" x:Key="txtStyle">
      <Setter Property="Foreground" Value="Red" />
   </Style>
</ResourceDictionary>

Blue.xaml:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

   <Style TargetType="Button" x:Key="BtnStyle">
      <Setter Property="Foreground" Value="Blue" />
   </Style>
   <Style TargetType="TextBlock" x:Key="txtStyle">
      <Setter Property="Foreground" Value="Blue" />
   </Style>
</ResourceDictionary>

由於MainPage中已經繫結了資原始檔中的樣式,所以系統啟動時就必須載入某一個樣式檔案,就是所謂的預設樣式,所以要加一個靜態類,來實現系統啟動時載入預設樣式和切換樣式,程式碼如下:

ThemeHelper.cs

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightChangeTheme
{
   public static class ThemeHelper
   {
      /// <summary>
      /// 載入樣式檔案到Application.Current.Resources
      /// </summary>
      /// <param name="theme"></param>
      public static void LoadTheme(string theme)
      {
         ResourceDictionary rd = new ResourceDictionary();
         if (theme.Length == 3)
         {
            Application.LoadComponent(rd, new Uri("/SilverlightChangeTheme;component/Red.xaml", UriKind.Relative));
         }
         else
         {
            Application.LoadComponent(rd, new Uri("/SilverlightChangeTheme;component/Blue.xaml", UriKind.Relative));
         }
         //清空Application.Current.Resources,存放新的樣式
         if (Application.Current.Resources.Count > 0)
         {
            Application.Current.Resources.Clear();
         }
         Application.Current.Resources.MergedDictionaries.Add(rd);
      }

      /// <summary>
      /// 從Application.Current.Resources中獲取指定名稱的樣式
      /// </summary>
      /// <param name="name"></param>
      /// <returns></returns>
      public static object FindResource(string name)
      {
         if (App.Current.Resources.Contains(name))
         {
            return App.Current.Resources[name];
         }
         else
         {
            return null; //這裡返回NULL,如果沒有控制元件會變成系統預設樣式。
         }
      }
   }
}

然後在App.xaml.cs中,在Application_Startup方法中新增如下程式碼:

private void Application_Startup(object sender, StartupEventArgs e)
      {
         //載入預設樣式
         ThemeHelper.LoadTheme("Blue");
         this.RootVisual = new MainPage();
      }

這樣啟動時就會自動載入藍色的風格了,效果圖下:

然後,給MainPage的Button新增事件,實現樣式的切換,程式碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightChangeTheme
{
   public partial class MainPage : UserControl
   {
      bool IsRed = false;
      public MainPage()
      {
         InitializeComponent();
      }

      private void button1_Click(object sender, RoutedEventArgs e)
      {
         if (IsRed)
         {
            //載入樣式到Application.Current.Resources
            ThemeHelper.LoadTheme("Blue");
            IsRed = false;
         }
         else
         {
            //載入樣式到Application.Current.Resources
            ThemeHelper.LoadTheme("Red");
            IsRed = true;
         }
         //執行時,更新樣式必須重新設定每個控制元件的Style,然後呼叫this.UpdateLayout()方法更新頁面。
         button1.Style = ThemeHelper.FindResource("BtnStyle") as Style;
         textBlock1.Style = ThemeHelper.FindResource("txtStyle") as Style;
         this.UpdateLayout();
      }
   }
}

這樣就實現了樣式的切換,需要注意的是系統啟動後切換樣式,要在程式碼中重新設定每個控制元件的Style,然後呼叫this.UpdateLayout()方法更新頁面。

當然,如果有多窗體的話,沒有開啟的話是不需要設定的,只需要設定已經顯示的控制元件。

 

補充知識:

關於Uri路徑的寫法。

XAML檔案的相對Uri訪問, 如<Image Source="silverlight.png" />或是<Image Source="./silverlight.png" />,

在子資料夾裡的可以用<Image Source=”./images/sl.jpg” />訪問到
最保險的方式是採用特有的程式集資源URI訪問,格式為
<Image Source="/{assemblyShortName};component/Foo.jpg"/>, 這種方式還可以引用到xap中的其他程式集中的圖片

 

修改我們的兩個圖片的引用方式為

<Image Source="/SilverlightApplication1;component/silverlight.png"/>
<Image Source="/SilverlightApplication1;component/images/sl.jpg" Height="100"/>  

 

點選這裡下載原始碼

 

相關文章