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:
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.