top of page

Beautify your WPF Apps with Material Design

If your users use Citrix to run Eclipse, your scripts may look like they're running in Windows 95. Buttons are flat and grayish, text boxes and lists are sunk in, and selections are too strong. Also, if you're developing on your own computer (not through Citrix), the UI that you see is different from what your users see (the Windows 95 look).


Perhaps you've tried to improve your scripts' appearance by tweaking individual controls—changing the color of a button or the style of a progress bar. I've gone as far as creating my own WPF theme. It was painful. It took me several days, and some controls still don't look quite right.


In my search for a free, easy to use, and attractive WPF theme, I found the Material Design in XAML Toolkit. It's based on Google's Material Design guidelines for user interfaces, guidelines they use on their mobile and web apps. The Material Design in XAML Toolkit repository contains a demo project that showcases the theme for various controls.


Applying the Material Design theme on your own app is straightforward. The steps are in the Getting Started wiki page, but they assume that you're developing a stand-alone app. If you're developing a binary plug-in script (i.e., a class library), you'll need to make some changes.


In a binary plug-in script, you'll find that you don't have an App.xaml, where the theme resource locations are supposed to be specified. To get around this, create a file called Theme.xaml and put the information there:


<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
        <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
        <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
        <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

You'll need to tell each of your windows to use the resources defined in Theme.xaml, so add the following to each of your windows' XAML file:


<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Theme.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>

There's another tricky thing. Because you don't use any classes in the Material Design assemblies, your script assembly doesn't load those assemblies. It's the XAML parser that uses the Material Design assemblies and therefore tries to load them. The problem is that, because it's not your assembly that loads them, .NET looks for the Material Design assemblies in the wrong place. To fix this, instantiate a couple of objects from the Material Design assemblies. I do it right before initializing the main window's components:


public MainWindow()
{
    InitializeMaterialDesign();
    InitializeComponent();
}

private void InitializeMaterialDesign()
{
    // Create dummy objects to force the MaterialDesign assemblies to be loaded
    // from this assembly, which causes the MaterialDesign assemblies to be searched
    // relative to this assembly's path. Otherwise, the MaterialDesign assemblies
    // are searched relative to Eclipse's path, so they're not found.
    var card = new Card();
    var hue = new Hue("Dummy", Colors.Black, Colors.White);
}

Now you should be ready to go! Continue to follow the instructions in the Getting Started wiki page to configure the colors and other window properties.

Related Posts

See All

ESAPI Essentials 1.1 and 2.0

A few months ago, I introduced ESAPI Essentials—a toolkit for working with ESAPI (available via NuGet). I've recently added one major feature: asynchronous access to ESAPI for binary plugin scripts. Y

Announcement: ESAPI Subreddit

A few months ago, Matt Schmidt started the ESAPI subreddit. It's another useful resource for finding and discussing ESAPI-related topics. According to the description, This community is to post and di

Dump All Patient Data from ESAPI

If, for whatever reason, you need to dump out all of the data for a patient from ESAPI, there's a quick and dirty way to do it. Well, there are probably several ways to do it, but here's one I've foun

bottom of page