Does XAML have a conditional compiler directive for debug mode?

C#WpfXaml

C# Problem Overview


I need something like this for styles in XAML :

<Application.Resources>

#if DEBUG
    <Style TargetType="{x:Type ToolTip}">
        <Setter Property="FontFamily" Value="Arial"/>
        <Setter Property="FlowDirection" Value="LeftToRight"/>
    </Style>
#else
    <Style TargetType="{x:Type ToolTip}">
        <Setter Property="FontFamily" Value="Tahoma"/>
        <Setter Property="FlowDirection" Value="RightToLeft"/>
    </Style>
#endif

</Application.Resources>
    

C# Solutions


Solution 1 - C#

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.

Solution 2 - C#

This is not possible in WPF/Silverlight/WP7.

On an interesting note, the standards document, ISO/IEC 29500 (Office Open XML File Formats), covers how this should be handled in an XML document, and XAML does support one of the items from that spec mc:Ignorable which allows us to do things like this:

<Page xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:c="Comments"
      mc:Ignorable="c">
    <Button Content="Some Text"
            c:Content="Some other text" />
</Page>

to comment out attributes.

The XAML parser team (SL4, WP7.1, WPF) chose to use that spec to solve their needs for ignoring attributes, rather than just making something up. That is why some of the default XAML pages have the 'mc' namespace defined. I do think it would be cool if XAML one day supported the rest of the spec that allows the loading of alternate content.

The mc:Ignorable attribute is used by Blend to support design time functionality.

Solution 3 - C#

You could use a template selector. The DataTemplateSelector class is something you code. With the template selection method that you override, you could put your preprocessor directives.

http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector.aspx

Solution 4 - C#

I wasn't happy with any of these and did this:

In my XAML I put any attributes or tags with a space just so i know I am screwing with them in the .cs file.

<Window x:Class="...
    mc:Ignorable="d"
    Title="" 
    BorderThickness="2"
    WindowStartupLocation="CenterScreen"
    ResizeMode="NoResize"
    Height="200" 
    Width="500"
    
    WindowStyle="None"    
    >

then in my code behind I do this:

    public partial class ScanProgressWindow : Window
    {
        public ScanProgressWindow()
        {
            InitializeComponent();
 #if DEBUG
            this.WindowStyle = WindowStyle.SingleBorderWindow;
 #endif
        }
    }

Works for me.

Solution 5 - C#

I feel like the given answers aren't the easiest to use. Here is my solution using a custom attachable dependency property:

using namespace Utility{
    public static class DebugVisibility
    {
        public static readonly DependencyProperty IsVisibleProperty = DependencyProperty.RegisterAttached(
    "Debug", typeof(bool?), typeof(DebugVisibility), new PropertyMetadata(default(bool?), IsVisibleChangedCallback));

        private static void IsVisibleChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var fe = d as FrameworkElement;
            if (fe == null)
                return;
#if DEBUG
            fe.Visibility = Visibility.Visible;
#else
            fe.Visibility = Visibility.Collapsed;
#endif
        }

        public static void SetIsVisible(DependencyObject element, bool? value)
        {
            element.SetValue(IsVisibleProperty, value);
        }

        public static bool? GetIsVisible(DependencyObject element)
        {
            return (bool?)element.GetValue(IsVisibleProperty);
        }
    }
}

and the xaml would be used like this:

<window ... xmlns:Util="clr-namespace:MyNamespace.Utility" >
    <Label Util:DebugVisibility.IsVisible="True">
</window>

I kept it as a bool in case you wanted to add some other visibility logic in there. This is a nice simple toggle that can be bound to and attached to any control

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEhsan Zargar ErshadiView Question on Stackoverflow
Solution 1 - C#bj0View Answer on Stackoverflow
Solution 2 - C#JasonRShaverView Answer on Stackoverflow
Solution 3 - C#Josh C.View Answer on Stackoverflow
Solution 4 - C#Sanford A StaabView Answer on Stackoverflow
Solution 5 - C#Dallin BeullerView Answer on Stackoverflow