In this post, I will show my attempt to change the Theme of SL application without reloading the app.
you can see a demo here . There are 3 main steps
1. Isolate all the styles into individual files .xaml or xml
2. load all the resources and save them
3. clear the Application Resources before the content is initialized
I modified the Red and Flat styles from Corrina http://blogs.msdn.com/corrinab/archive/2008/06/16/8602865.aspx) to include namespaces on all of them
It allows switching between 3 themes.
Here are the screenshots
The main(page.xaml) content is as follows
<Grid x:Name=”LayoutRoot” >
<ContentControl x:Name=”cc1″ Width=”700″ Height=”500″/>
<ContentControl x:Name=”cc2″
Width=”300″
Height=”50″
HorizontalAlignment=”Right”
VerticalAlignment=”Top” />
</Grid>
cc2 is the ContentControl into which usercontrol(ThemeSelection) will be loaded. cc1 is the ContentControl into which the actual content will be loaded
The codebehind(page.xaml.cs) constructor has the following
public Page()
{
IsolatedStorageSettings.ApplicationSettings.Clear();
GetThemes(“Default”);
GetThemes(“Red”);
GetThemes(“Flat”);
InitializeComponent();
LayoutRoot.Background = App.Current.Resources[“BkgBrush”] as SolidColorBrush;
ThemeSelection ts = new ThemeSelection(“DefaultTheme”);
cc2.Content = ts;
ts.ThemeChanged += new ThemeSelection.ThemeChangedEventHandler(ts_ThemeChanged);
MainContent mc = new MainContent();
cc1.Content = mc;
}
what we are doing is clearing the ApplciationSettings, getting styles for different themes using StreamResourceInfo and populating a list which inturn is added to ApplicationSettings. When the theme is changed the Usercontrol(where we make the theme selection), raises an event which is handled like this
void ts_ThemeChanged(object sender, ThemeChangedEventArgs e)
{
ThemeSelection ts = new ThemeSelection(e.Theme);
cc2.Content = ts;
MainContent mc = new MainContent();
cc1.Content = mc;
ts.ThemeChanged += new ThemeSelection.ThemeChangedEventHandler(ts_ThemeChanged);
LayoutRoot.Background = App.Current.Resources[“BkgBrush”] as SolidColorBrush;
}
The UserControl(MainContent.xaml) has the applciation specific logic, nothing special w.r.t themes, except for the fact that the current selection is maintained in the listbox by saving the selected item in IsolatedStorageSettings.ApplicationSettings.
ThemeSelection.xaml is the UserControl where we make the ThemeSelection which has logic to raise the event, when the theme changes we reload. The contentControls clear the App.Resources and load the styles from IsolatedStorageSettings.ApplicationSettings
private void SetTheme(string s)
{
App.Current.Resources.Clear();
List<Theme> themeSettings = new List<Theme>();
themeSettings = IsolatedStorageSettings.ApplicationSettings[s] as List<Theme>;
foreach (Theme t in themeSettings)
App.Current.Resources.Add(t.Key, XamlReader.Load(t.Value));
}
It doesnt have any optimizations or error checking, so the initial load(bit slow) and time for changing themes could be reduced by some variations
you can download the source here
please leave a comment if you have any variations that you come up with.
great work
I was looking at this http://www.nikhilk.net/Silverlight-Themes.aspx. Probably what it does internally is the same as you have mentioned here.
Thanks for the details.
hi, it does not work in sl 2.0 RTM, it throw Value of local:DataGridColumnHeader of Property TargetType invalid, [Line: 1 Position: 413]
local:DataGridColumnHeader of Property TargetType invalid, [Line: 1 Position: 413]
getting this error too, SL2
DataGrid has changed a lot since this post. so this will not work as some of the types have changed. I dont have sl2 installed
I’ve been looking so many places for thsi information.