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. #if directive can be used not only to test for symbols DEBUG and RELEASE. We are able to define any symbols. Let’s take a look how to do that and how to use newly defined symbol in the code. For example, we want to add some funny log messages when symbol FUN_MODE is defined.
- First, define a new compilation symbol for the whole project in the project’s properties:
- Then we can check for 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 is quite simple. The question is how to achieve the same in XAML code.
We’ve already defined custom compilation symbol and want to show different content on the view depends on the symbol FUN_MODE presence. Hopefully, Open XML provides an 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 XML namespace.
- Use 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
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.
- Define Fun_Mode in the view and use AlternateContent to provide 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 (but 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 used Choice elements.
Now in order to disable fun mode we need just to remove compilation symbol FUN_MODE from the project’s properties. That will disable definition of 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 Fallback element will be used.
In case we need to show the text only when FUN_MODE isn’t defined we just need to leave the Choice element empty.