How to load a DictionaryStyle.xaml file at run time?
Changing a theme or style at run-time is possible by assigning styles using DynamicResource binding and loading a ResourceDictionary (XAML) from a Content file at run-time.
This can be done by loading a DictionaryStyle.xaml at run time.
If you would prefer to just jump right in, download the source code: RuntimeLoadOfResourceDictionaryExample.zip
Step 1 – Create a new WPF Application project in Visual Studio
- In Visual Studio, go to File | New | Project.
- Select WPF Application.
- Provide a name for the project and make sure the path is correct.
- Click OK.
Step 2 – Create a basic WPF User Interface
- Create a basic interface.
Note 1: You can make one yourself, or you can use the basic interface I used. Just copy and paste from below.
Note 2: I have already added a menu for selecting the Blue or Grey for you. - Set the Style to use DynamicResource binding.
-
<Window x:Class="RuntimeLoadOfResourceDictionaryExample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Style="{DynamicResource ResourceKey=MainWindowStyle}" > <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="30" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="25" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="15" /> <ColumnDefinition Width="*" MinWidth="100"/> <ColumnDefinition Width="*" MinWidth="200"/> <ColumnDefinition Width="15" /> </Grid.ColumnDefinitions> <DockPanel Grid.ColumnSpan="4" > <Menu DockPanel.Dock="Top" > <MenuItem Header="_File"> <MenuItem Header="E_xit" Click="MenuItem_Exit_Click" /> </MenuItem> <MenuItem Header="_Styles"> <MenuItem Name="BlueStyle" Header="_Blue" Click="MenuItem_Style_Click" /> <MenuItem Name="GreyStyle" Header="_Grey" Click="MenuItem_Style_Click" /> </MenuItem> </Menu> </DockPanel> <Label Content="First Name" Name="label1" Grid.Row="2" FlowDirection="RightToLeft" Grid.Column="1" /> <Label Content="Age" Name="label3" Grid.Row="3" FlowDirection="RightToLeft" Grid.Column="1" /> <Label Content="Last Name" Name="label2" Grid.Row="4" FlowDirection="RightToLeft" Grid.Column="1" /> <TextBox Name="textBox1" Grid.Column="2" Grid.Row="2" /> <TextBox Name="textBox2" Grid.Column="2" Grid.Row="3" /> <TextBox Name="textBox3" Grid.Column="2" Grid.Row="4" /> <Button Content="Clear" Grid.Column="2" Grid.Row="5" Height="23" HorizontalAlignment="Right" Name="button1" VerticalAlignment="Top" Width="75" /> </Grid> </Window>
- Also populate the MainWindow.xaml.cs file with the code-behind needed for some of the events.
private void MenuItem_Exit_Click(object sender, RoutedEventArgs e) { Environment.Exit(0); } private void MenuItem_Style_Click(object sender, RoutedEventArgs e) { MenuItem mi = sender as MenuItem; string stylefile = Path.Combine(App.Directory, "Styles", mi.Name + ".xaml"); App.Instance.LoadStyleDictionaryFromFile(stylefile); }
It won’t compile just yet as some of the code doesn’t exist yet.
Step 3 – Add code to read in a ResourceDictionary at runtime
This is going to take place in the App.xaml.cs file. App.xaml.cs is the ultimate parent and by loading the ResourceDictionary here, every child will have access to them. This especially becomes important with larger projects where WPF UI elements, controls, windows, or others may come from other dlls.
- Open the App.xam.cs file as shown below.
- Add a function to load the ResourceDictionary at runtime.
- Now add some member variables and create a constructor that loads a style by default.Your class should now look as follows:
using System; using System.IO; using System.Windows; using System.Windows.Markup; namespace RuntimeLoadOfResourceDictionaryExample { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : Application { public static App Instance; public static String Directory; private String _DefaultStyle = "BlueStyle.xaml"; public App() { Instance = this; Directory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); string stringsFile = Path.Combine(Directory, "Styles", _DefaultStyle); LoadStyleDictionaryFromFile(stringsFile); } /// <summary> /// This funtion loads a ResourceDictionary from a file at runtime /// </summary> public void LoadStyleDictionaryFromFile(string inFileName) { if (File.Exists(inFileName)) { try { using (var fs = new FileStream(inFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Read in ResourceDictionary File var dic = (ResourceDictionary)XamlReader.Load(fs); // Clear any previous dictionaries loaded Resources.MergedDictionaries.Clear(); // Add in newly loaded Resource Dictionary Resources.MergedDictionaries.Add(dic); } } catch { } } } } }
Now, we haven’t create the default style yet, don’t fret, that is the next step.
Step 4 – Create Some Styles
- In Visual Studio, add a new folder to your project called Styles.
- Right-click on the folder and choose Properties.
- Set the Namespace Provider value to false.
- Right-click on the Styles folder and choose Add | Resource Dictionary.
- Provide a file name and make sure that Resource Dictionary (WPF) is selected.
Note: I named my first resource dictionary BlueStyle.xaml. - Click Add.
- Right-click on the BlueStyle.xaml file and choose Properties.
- Set ‘Build Action’ to ‘Content’.
- Set ‘Copy to Output Directory’ to be ‘Copy if newer’.
- Set ‘Custom Tool’ to blank.
- Populate the BlueStyle.xaml with your desired style. Here is the simple style I used for this example.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style x:Key="MainWindowStyle" TargetType="Window"> <Setter Property="SizeToContent" Value="WidthAndHeight" /> <Setter Property="Background" Value="RoyalBlue" /> </Style> <Style TargetType="Label"> <Setter Property="Margin" Value="0,5,0,5" /> </Style> <Style TargetType="TextBox"> <Setter Property="Margin" Value="0,5,0,5" /> </Style> </ResourceDictionary>
- Create a copy of the style named GreyStyle.xaml.
- Repeat steps 7 thru 10 for this new file.
- In the GreyStyle.xaml, change the Background of the MainWindowStyle to DarkGrey.
Step 5 – Build and test
Your project should now be working. You should be able to build and run it. You should be able to click on Styles and change the style.