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
- Contains your
ProjectB
Contains the
XmlsDefinitionAttribute
with the namespace ofTestingAlternateContent
:#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
Is There Any Benefit to This Switch/Pattern Matching Idea
Observeon and Subscribeon - Where the Work Is Being Done
Return View as String in .Net Core
Ignore Mapping One Property with Automapper
Open Image from File, Then Release Lock
Getfiles with Multiple Extensions
C# Using Reflection to Copy Base Class Properties
Ienumerable and Recursion Using Yield Return
How to Serialize a C# Anonymous Type to a JSON String
How to Add Assembly References in Visual Studio Code
Algorithm for Simplifying Decimal to Fractions
Format of the Initialization String Does Not Conform to Specification Starting at Index 0
How to Stop Entity Framework from Trying to Save/Insert Child Objects
Access to Modified Closure (2)