Mahapps controls customization

By | July 8, 2015

This is a brief tutorial on how to change the look and feel of Mahapps controls. I will be making a small change to Mahapps datagrid to demonstrate the steps.

Anyone who has been working with WPF for a reasonable amount of time must have come across Mahapps. In case you haven’t then you must check them out. They have done some awesome work. The world of WPF is a little less cruel thanks to them.

Why
One of the delightful features of Mahapps is the DataGrid. They really make the plain old data grid shine. To put it graphically, with plain old WPF you will see:
WPF datagrid

With Mahapps you see:
Mahapps datagrid

However one of the modifications you will notice here is that the Header columns are all in upper case. Which makes sense for 99% of the cases. But sometimes the design team warrants that the column headers should not be in upper case.

What do you do then?
One extreme way is to download the source code and make the changes. Then compile and replace the dll’s in the package directory created by Nuget. But there is a better and simple solution.
You can create a style based on Mahapps control style and make change/add the parts you want.

How

  1. First create the WPF project.
  2. Install the Mahapps.Metro via Nuget.
  3. Follow the quick start guide to make sure that the Mahapps is up and running for your project.
  4. Then create a resource file to contain the style you want for your control.
  5. Inside the resource file you create a merged dictionary to pull in the desired mahapps control as a static resource.
  6. Create your own style based on mahapps control style.
  7. In your XAML you then create a merged dictionary to pull in your custom style.
  8. Apply the style on your controls.
  9. Done.

Steps 1, 2 and 3 are easy to do.

Step 4:
This step involves some work. I did download the source code and went looking for the DataGrid control XAML. Once that was found I found where the Column Headers were getting converted to upper case.

I will just post snippets rather than the whole Controls.DataGrid.xaml.

<Converters:ToUpperConverter x:Key="ToUpperConverter" />

Converter declared.

<Style x:Key="MetroDataGridColumnHeader"
           TargetType="{x:Type DataGridColumnHeader}">

The Style which is responsible for the making the Column header all upper case.

<Setter Property="ContentTemplate">
	<Setter.Value>
		<DataTemplate>
			<TextBlock FontWeight="SemiBold"
				Text="{Binding Converter={StaticResource ToUpperConverter}}" />
		</DataTemplate>
	</Setter.Value>
</Setter>

The converter in action.

What I will do is to create my own style based on MetroDataColumnHeader and then get rid of the converter. Simple.

This is what my Resource file, CustomDataGridStyle.xaml looks like.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/controls.datagrid.xaml" />
    </ResourceDictionary.MergedDictionaries>

    <Style x:Key="DemoDataGridColumnHeader"
           TargetType="{x:Type DataGridColumnHeader}"
           BasedOn="{StaticResource MetroDataGridColumnHeader}">
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <TextBlock FontWeight="SemiBold"
                               Text="{Binding}" />
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style x:Key="CustomDataGrid"
           TargetType="{x:Type DataGrid}"
           BasedOn="{StaticResource MetroDataGrid}">
        <Setter Property="ColumnHeaderStyle"
                Value="{StaticResource DemoDataGridColumnHeader}" />
    </Style>
</ResourceDictionary>
  • Line 4: I pull in the controls.datagrid.xaml. If your mahapps install is correct and working you will get no errors here.
  • Line 7: I create a new DataGridColumnHeader style called DemoDataGridColumnHeader.
  • Line 8: I keep DataGridColumnHeader of WPF as the target.
  • Line 9: This is crucial. I base this style on MetroDataGridColumnHeader. The reason is that there is lot of good stuff in there which is I am going to keep. The only part which I do not want will be changed.
  • Line 14: This is where I make the change. The ToUpperConverter is removed.
  • Line 20: I define a new style called CustomDataGrid.
  • Line 21: I make this style target WPF DataGrid.
  • Line 22: I base it on the Mahapps MetroDataGrid. Again because I want all the good stuff which will make the Data grid shine.
  • Line 23: But I single out one Property, ColumnHeaderStyle.
  • Line 24: I want it to use my DemoDataGridColumnHeader rather than the MetroDataGridColumnHeader.

My MainWindow.xaml looks like this:

<controls:MetroWindow x:Class="Demo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="CustomDataGridStyle.xaml" />
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Grid.Resources>

        <DataGrid ItemsSource="{Binding}"
                  SelectionMode="Extended" SelectionUnit="FullRow"
                  IsReadOnly="True"
                  FontSize="{DynamicResource NormalFontSize}"
                  AutoGenerateColumns="True"
                  Style="{StaticResource CustomDataGrid}"
                  HorizontalScrollBarVisibility="Auto">
        </DataGrid>
    </Grid>
</controls:MetroWindow>
  • Line 10: I pull in the style from the resource file.
  • Line 20: I apply the style to the DataGrid.

And the output is:
Customised Mahapps datagrid

Incase you were wondering where the data is coming from here are the files.

//SampleData.cs
namespace Demo
{
    public class SampleData
    {
        public string Name { get; set; }

        public string Address { get; set; }

        public string Email { get; set; }

        public SampleData(string name, string address, string email)
        {
            Name = name;
            Address = address;
            Email = email;
        }
    }
}
//MainWindow.xaml.cs
using System.Collections.Generic;

namespace Demo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        public List<SampleData> SampleDataSet { get; set; }

        public MainWindow()
        {
            InitializeComponent();

            SampleDataSet = new List<SampleData>
            {
                new SampleData("Bob", "USA", "Rob@email.com"),
                new SampleData("Martin", "Canada", "Martin@email.com")
            };

            DataContext = SampleDataSet;
        }
    }
}

One thought on “Mahapps controls customization

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.