Post

Create new MahApps window in separate thread

So, as the title says, people often want to show a window in a separate ui thread. If we now google about this we can find many articles which explain the whole situation and which also show some code snippets. But sometimes there are situations where this code doesn’t work. This is often requested by people who use MahApps.Metro.

How can I run a MetroWindow in a separate thread? Can you explain why I get this exception?

1
Exception thrown: 'System.Windows.Markup.XamlParseException' in PresentationFramework.dll

So, here are two blog articles which explain the problem and also explain a solution:

Here is my solution with MahApps.Metro that works on my machine™.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// Create a thread
var newWindowThread = new Thread(new System.Threading.ParameterizedThreadStart((state) =>
{
    // Create our context, and install it:
    SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher));

    // Create and show the Window
    var testWindow = new MetroWindow()
    {
        WindowStartupLocation = WindowStartupLocation.CenterScreen,
        Title = "Window in separate thread...",
        Width = 500,
        Height = 300,
        BorderThickness = new Thickness(1)
    };
    // To solve System.Windows.Markup.XamlParserException the resources must be merged with the resource dictionary of window but not application.
    testWindow.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri("/PresentationFramework.Aero, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=MSIL;component/themes/aero.normalcolor.xaml", UriKind.RelativeOrAbsolute) });
    testWindow.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml") });
    testWindow.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml") });
    testWindow.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml") });
    testWindow.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Accents/Red.xaml") });
    testWindow.Resources.MergedDictionaries.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml") });
    testWindow.SetResourceReference(MetroWindow.BorderBrushProperty, "AccentColorBrush");
    testWindow.Closed += (o, args) =>
    {
        Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
        testWindow = null;
    };
    testWindow.Show();

    // Start the Dispatcher Processing
    System.Windows.Threading.Dispatcher.Run();
}));
// Set the apartment state
newWindowThread.SetApartmentState(ApartmentState.STA);
// Make the thread a background thread
newWindowThread.IsBackground = true;
// Start the thread
newWindowThread.Start();

It’s also possible to use a custom MetroWindow instead creating an empty window. In this case it’s necessary to put the MahApps resources in the XAML code of the window itself.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<controls:MetroWindow x:Class="MetroDemo.ExampleWindows.CustomWindow"
                      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                      xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
                      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                      Title="CustomWindow"
                      Width="300"
                      Height="300"
                      mc:Ignorable="d">

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Red.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <Grid>

        <ComboBox x:Name="comboBox1"
                  Width="170"
                  Height="48"
                  Margin="10"
                  HorizontalAlignment="Left"
                  VerticalAlignment="Top">
            <ComboBoxItem>Test 1</ComboBoxItem>
            <ComboBoxItem>Test 2</ComboBoxItem>
        </ComboBox>

    </Grid>
</controls:MetroWindow>

Simply change

1
var testWindow = new CustomWindow()

2016-01-22_16h12_04

This post is licensed under CC BY 4.0 by the author.