Compilation directives for controlling XAML content

In C# in order to control what code should be executed we can use compilation directives #if, #else, #elif and #endif. For instance, we can compile certain code only in Debug mode and exclude one in Release.

The question is how to achieve the same in XAML.

Directive #if can be used not only to test for symbols DEBUG and RELEASE. We are able to define any symbols. Let's take a look at how to do that and how to use a newly defined symbol in the code. For example, we want to add some funny log messages when the symbol FUN_MODE is defined.

First, define a new compilation symbol for the whole project in the project’s properties:

compilation-symbols

Then, we check for the defined symbol in the code:

#if FUN_MODE
    logger.Debug("Yahoo! It looks like our app finally works!");
#else
    logger.Debug("Application started.");
#endif

Everything looks quite simple.

We've already defined a custom compilation symbol and want to show different content on the view depends on the symbol FUN_MODE presence. Fortunately, Open XML provides the AlternateContent element that works similarly to switch in C#. It provides a possibility to check defined XML namespaces and make a choice between different content. However, we need to do a little trick to map our compilation symbol to an XML namespace.

First, use the XmlnsDefinitionAttribute in the project's AssemblyInfo.cs to create a new XML namespace definition, and surround it with the compilation directives #if ... #endif.

#if FUN_MODE
[assembly: XmlnsDefinition("Fun_Mode", "MySolution.ProjectNamespace")]
#endif

The project's assembly has the Fun_Mode definition only when FUN_MODE symbol is defined. The right namespace of the project should be used as the second parameter.

Second, define Fun_Mode in the view and use AlternateContent to provide a different XAML:

<UserControl x:Class="MySolution.ProjectNamespace.LoginView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:fun="Fun_Mode"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
  <Grid>
    <mc:AlternateContent>
      <mc:Choice Requires="fun">
        <TextBlock Text="Hi! As usual enter admin:111 and have a nice day! :)" />
      </mc:Choice>
      <mc:Fallback>
        <TextBlock Text="Welcome! Please, enter your login and passsword." />
      </mc:Fallback>
    </mc:AlternateContent>
  </Grid>
</UserControl>

AlternateContent contains one or many Choice elements (at least one is required). Choice.Requires points to the XML namespace definition (xmlns:fun in the example). If it is defined then XAML code inside the Choice element is used. A code inside the Fallback element is used when there are no Choice elements found which meet the Requires condition.

Now, in order to disable fun mode, we need just to remove the compilation symbol FUN_MODE from the project's properties. It will disable the definition of the assembly attribute. And, as a result, xmlns:fun will point to nothing. The code in the Choice element will be ignored and the code in the Fallback will be used instead.

In case we need to show the text only when FUN_MODE isn't defined we just leave the Choice element empty.