Running code in a XAML designer at design-time

Recently I needed to show dynamic values in the XAML designer (WPF, Silverlight, Windows Phone, WinRT) to show real-time translations through a LanguageService that were wrapped in a markup extension. That sounds complex, but below is an image that shows what I wanted to achieve:

image

As the image shows, I needed quite some dynamic content to be loaded during design-time. When running the application, I can easily customize the IoC container in App.xaml.cs, but that doesn’t work at design-time.

After some searching on the internet, I found this article by Josh Smith.Unfortunately the Visual Studio 2013 designer (and maybe other versions as well) doesn’t load the assembly attributes thus it was not working for me. Though the solution represented below is part of Catel, it can be used without it as well.

Introducing the DesignTimeCode attribute

To allow users to run code in the designer (Visual Studio or Blend), we first need to introduce the DesignTimeCodeAttribute. This is an assembly-wide attribute which will specify the class to create at design time (just like Josh Smith recommended). This means that it is possible to create multiple attributes. Below is the class definition:

Below is an example of the usage of the attribute:

Introducing the DesignTimeInitializer

The DesignTimeCodeAttribute contains the types that are constructed during design-time. The problem is that every type specified in the DesignTimeCodeAttribute must check whether it is running in design mode, otherwise it might also fire at runtime. The DesignTimeInitializer base class will aid developers in process and check for this in the constructor.

Below is an example of the usage of the DesignTimeInitializer:

Making it actually run code at design-time

So far, we haven’t done much different from the solution Josh Smith provided. However, it was still not working at this level for me. The reason is that the Visual Studio 2013 designer does not read the assembly attributes and thus will not create our design time initializers.

The solution here is a two-step process, and requires the use of ModuleInit.Fody. If you are not familiar with ModuleInit.Fody, you can read about it here. Basically it allows you to run code as soon as an assembly is loaded (a.k.a. assembly-wide constructors). Installing it is really simple via NuGet.

The next step we need to take is to add initialization code as soon as our assembly is loaded. The code below reads the attribute from all loaded assemblies and initializes the code:

Checking out the final result

Below is a short gif showing that the designer now runs code at design-time. It does this by registering a custom source in the LanguageService. Then every time the project is rebuilt, the LanguageService is updated and will reflect the changes at design time.

Running code at design time