Does Xaml Have a Conditional Compiler Directive for Debug Mode

Does XAML have a conditional compiler directive for debug mode?

I recently had to do this and was suprised at how simple it was when I couldn't easily find any clear examples. What I did was add the following to AssemblyInfo.cs:

#if DEBUG
[assembly: XmlnsDefinition( "debug-mode", "Namespace" )]
#endif

Then, use the markup-compatability namespace's AlternateContent tag to choose your content based on the presense of that namespace definition:

<Window x:Class="Namespace.Class"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="debug-mode"

Width="400" Height="400">

...

<mc:AlternateContent>
<mc:Choice Requires="d">
<Style TargetType="{x:Type ToolTip}">
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FlowDirection" Value="LeftToRight"/>
</Style>
</mc:Choice>
<mc:Fallback>
<Style TargetType="{x:Type ToolTip}">
<Setter Property="FontFamily" Value="Tahoma"/>
<Setter Property="FlowDirection" Value="RightToLeft"/>
</Style>
</mc:Fallback>
</mc:AlternateContent>

...
</Window>

Now, when DEBUG is defined, "debug-mode" will also be defined, and the "d" namespace will be present. This makes the AlternateContent tag choose the first block of code. If DEBUG is not defined, the Fallback block of code will be used.

This sample code was not tested, but it's basically the same thing that I'm using in my current project to conditionally show some debug buttons.

I did see a blog post with some example code that relied on the "Ignorable" tag, but that seemed a lot less clear and easy to use as this method.

Preprocessor conditional compilation in XAML

You can add some code in the constructor that enables/disables the elements:

public MainWindow()
{
InitializeComponent();

#if DEBUG
button1.IsEnabled = false;
#endif
}

Conditional Compile in XAML?

The technique illustrated in the linked question/answer may go some way towards giving conditional processing of XAML elements, but I don't think it is going to give you exactly what you are after.

There are another two options that may be better suited to your needs: programmatic conditional compilation and conditional inclusion at build time.

For the programmatic conditional compilation you can use regular conditional compilation in the code behind of your view (preferable as it's a UI element you're affecting) or in the viewmodel (not so pure, but totally acceptable if you have to include it in multiple layers). This conditional compilation can be used to either change what values are returned from properties (by changing which lines are compiled in and therefore executed) or by eliminating blocks of code (this is clunky but still effective), you can then have a XAML DataTrigger that has an expression dependent on the conditionally compiled code.

The other option is to specify control templates in a XAML resource file and either programmatically select them or use a MSBuild property in an ItemGroup expression in your proj file to control which files are included in the build. Combined with regular programmatic conditional compilation in your models/viewmodels this should give you a nice clean solution for your problem - in fact using this option you possibly don't even need the programmatic conditional compilation.

A TemplateSelector may also help, but IMVHO its a bit of a filthy hack. A TemplateSelector is supposed to swap a template based on type, but you can also exploit this to include extra code to determine the template to use - this could be a good spot to include conditionally compiled code.

How can I have WPF use one window style for Debug mode and another for Release mode?

Create a Style picker class:

namespace WpfApplication1
{
public class DebugReleaseStylePicker
{
#if DEBUG
internal static readonly bool debug = true;
#else
internal static readonly bool debug=false;
#endif

public Style ReleaseStyle
{
get; set;
}

public Style DebugStyle
{
get; set;
}

public Style CurrentStyle
{
get
{
return debug ? DebugStyle : ReleaseStyle;
}
}
}
}

in your App.xaml
add to your Application.Resources your debug and release style + a instance of the StylePicker and set the ReleaseStyle and DebugStyle to the previous set up styles:

<Application.Resources>
<Style x:Key="WindowDebugStyle">
<Setter Property="Window.Background" Value="Red"></Setter>
</Style>

<Style x:Key="WindowReleaseStyle">
<Setter Property="Window.Background" Value="Blue"></Setter>
</Style>

<WpfApplication1:DebugReleaseStylePicker x:Key="stylePicker"
ReleaseStyle="{StaticResource WindowReleaseStyle}"
DebugStyle="{StaticResource WindowDebugStyle}"/>
</Application.Resources>

In your Window markup set up the WindowStyle like this:

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
Style="{Binding Source={StaticResource stylePicker}, Path=CurrentStyle}">
..
</Window>

You can reuse the DebugReleaseStylePicker to set the style to any other control not just the Window.

WPF AlternateContent not working

The problem is that the XmlnsDefinitionAttribute is parsed after the XAML is parsed, so it doesn't work for the same assembly.

You can however, make that XmlnsDefinition in any other (referenced) project in your solution, and it'll work

That is:

  • ProjectA (Namespace: TestingAlternateContent)

    • Contains your MainWindow.Xaml
    • References ProjectB
  • ProjectB

    • Contains the XmlsDefinitionAttribute with the namespace of TestingAlternateContent:

      #if DEBUG
      [assembly: XmlnsDefinition("debug-mode", "TestingAlternateContent")]
      #endif

I just tested it, and it works fine, no modifications to either the assembly attribute declaration or to the Xaml, just adding it on a different project



Related Topics



Leave a reply



Submit