WPF is an incredibly powerful framework, but out of the box, it looks… well, like it’s 2010.
For years, the community standard for fixing this has been MaterialDesignInXAML (MDIX). It brings Google’s Material Design language to WPF with zero effort.
On the architectural side, Caliburn.Micro has been a favorite for its “Convention over Configuration” approach to MVVM.
But combining them can sometimes be tricky. How do you handle App.xaml resources? How do MDIX’s DialogHost overlays fit with Caliburn’s WindowManager?
In this post, we’ll walk through a complete integration.
1. The Setup
#First, create your WPF project and install the packages.
1
2
| Install-Package Caliburn.Micro
Install-Package MaterialDesignThemes
|
2. The App.xaml Merge
#This is the most common point of failure. Caliburn.Micro needs its Bootstrapper initialized in resources, and MDIX needs its dictionaries merged.
If you don’t merge them correctly, your app will either crash or look like standard Windows 95 controls.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| <Application x:Class="MyModernApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:MyModernApp">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- 1. Merge Material Design Dictionaries FIRST -->
<!-- Use BundledTheme for cleaner setup (MDIX 4.0+) -->
<materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
<!-- Essential Defaults -->
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- 2. Initialize Caliburn.Micro Bootstrapper -->
<local:Bootstrapper x:Key="Bootstrapper" />
</ResourceDictionary>
</Application.Resources>
</Application>
|
3. The ShellView Configuration
#In Caliburn.Micro, your main window is usually ShellView.xaml. To get the full Material Design effect (fonts, colors, ripple effects), you need to apply some properties to 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
| <Window x:Class="MyModernApp.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
<!-- Apply the Material Design Font and Colors globally -->
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextElement.FontWeight="Regular"
TextElement.FontSize="13"
TextOptions.TextFormattingMode="Ideal"
FontFamily="{DynamicResource MaterialDesignFont}"
<!-- Optional: Use the MD Window Style for a cleaner chrome -->
Style="{StaticResource MaterialDesignWindow}"
Title="My Modern App" Height="450" Width="800">
<!-- Your Content Here -->
<Grid>
<ContentControl x:Name="ActiveItem" />
</Grid>
</Window>
|
4. The Dialog Dilemma: WindowManager vs. DialogHost
#This is the biggest architectural clash.
- Caliburn.Micro uses
IWindowManager.ShowDialogAsync() to open a new Window (a modal). - Material Design encourages
DialogHost, which is an overlay on the existing window.
Overlays generally look more modern and “web-like” than popping up separate OS windows.
The Solution: A Dialog Service
#Don’t call DialogHost.Show directly from your ViewModel (that breaks MVVM). Instead, create a service.
The Interface:
1
2
3
4
5
| public interface IDialogService
{
Task ShowMessage(string message);
Task<bool> ShowConfirmation(string message);
}
|
The Implementation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| using MaterialDesignThemes.Wpf;
public class MaterialDialogService : IDialogService
{
public async Task ShowMessage(string message)
{
// Create a simple view for the message
var view = new TextBlock { Text = message, Margin = new Thickness(20) };
// "RootDialog" is the Identifier we will set in XAML
await DialogHost.Show(view, "RootDialog");
}
// ... implement confirmation similarly
}
|
The ShellView Update:
Wrap your content in a DialogHost.
1
2
3
4
5
| <materialDesign:DialogHost Identifier="RootDialog">
<Grid>
<ContentControl x:Name="ActiveItem" />
</Grid>
</materialDesign:DialogHost>
|
Now your ViewModels can inject IDialogService and show beautiful overlays without knowing about XAML.
5. Validation that Pops
#One of the best features of MDIX is the input validation styles. Caliburn.Micro supports IDataErrorInfo out of the box.
ViewModel:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| public class LoginViewModel : Screen, IDataErrorInfo
{
private string _username;
public string Username
{
get => _username;
set
{
_username = value;
NotifyOfPropertyChange(() => Username);
}
}
public string this[string columnName]
{
get
{
if (columnName == nameof(Username) && string.IsNullOrWhiteSpace(Username))
return "Username is required!";
return null;
}
}
public string Error => null;
}
|
View:
Just bind it. MDIX handles the rest automatically, showing the error text in red below the line.
1
2
3
| <TextBox Text="{Binding Username, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
materialDesign:HintAssist.Hint="Username"
Style="{StaticResource MaterialDesignFloatingHintTextBox}" />
|
6. Dynamic Theming
#Want to let the user switch between Light and Dark mode? MDIX makes this trivial with the PaletteHelper.
1
2
3
4
5
6
7
8
| public void ToggleTheme()
{
var paletteHelper = new PaletteHelper();
var theme = paletteHelper.GetTheme();
theme.SetBaseTheme(theme.GetBaseTheme() == BaseTheme.Dark ? BaseTheme.Light : BaseTheme.Dark);
paletteHelper.SetTheme(theme);
}
|
Summary
#Integrating MaterialDesignInXAML with Caliburn.Micro gives you the best of both worlds: a robust, testable architecture and a stunning, modern UI.
The key takeaways are:
- Merge Resources Correctly: MDIX first, then Bootstrapper.
- Use DialogHost: Prefer overlays over separate windows for a modern feel.
- Leverage Styles: Use
HintAssist and ValidatesOnDataErrors to make your forms sing.
Your WPF application doesn’t have to look like it was built in 2010. With these tools, you can create beautiful, modern interfaces that your users will love—and that your development team can maintain and test with confidence.
Further Reading
#