skip to Main Content

I use C# preprocessor directives extensively while developing. I define them either directly in .cs files or globally in the .csproj:

<PropertyGroup>
  <DefineConstants>fix_issue_001;fix_issue_002;</DefineConstants>
</PropertyGroup>

Or via command line as described here.

Then I use them to compartmentalize code:

#if fix_issue_001
// some new code
#else
// some old code
#endif

This helps me track changes, though I acknowledge it’s not the most readable or canonical approach. Version control and branching would be better, but we’re constrained to SVN and Visual Studio.

Now I want to extend this pattern to WPF XAML files. Since preprocessor directives aren’t available in XML, I’m looking at using XSLT to achieve similar functionality.

For example, I’d like to have something like this in my XAML:

<StackPanel>
    <!-- fix_issue_001:true -->
    <Button Content="Original version" Click="Button_Click" />
    <!-- end fix_issue_001:true -->

    <!-- fix_issue_001:false -->
    <Button Content="New version" Background="LightGreen" Click="Button_Click" />
    <!-- end fix_issue_001:false -->
</StackPanel>

The goal is to have XSLT transform this at build time, including/excluding sections based on whether fix_issue_001 is defined, just like #if/#else works in C#.

Requirements:

  • Maintain Visual Studio’s XAML designer functionality
  • Minimize changes to existing code
  • Prefer solutions using .csproj/.sln and/or other configurations so it works seamlessly inside Visual Studio
  • Command line (batch/PowerShell) solutions are acceptable if necessary (e.g., using xsltproc or Saxon-HE)

Is this possible? How would you implement it?

P.S. Posted a new question here.

2

Answers


  1. Its neither elegant nor exactly what you asked for but maybe you can go this direction:

    <Button Content="Original version" Click="Button_Click" Visibility="{Binding fix_issue_001, Converter={StaticResource boolToVisibility}}"/>
    <Button Content="New version" Background="LightGreen" Click="Button_Click" Visibility="{Binding fix_issue_001, Converter={StaticResource boolToInvisibility}}"/>
    

    alternativley you could create a converter that accepts a Name and a value as ConverterParameter and then checks the define and hides controls accordingly.

    Login or Signup to reply.
  2. The way we do this is to add attributes to the elements.

    <Button Content="Original version" Click="Button_Click" 
            v:fix_issue_010="true"/>
    
    <Button Content="New version" Background="LightGreen"                        
            Click="Button_Click" 
            v:fix_issue_010="false"/>
    

    I’ve put the attributes in a namespace here to distinguish them, but that’s your choice.

    The XSLT code to retain some elements and remove others is then trivial.

    For example, assuming the semantics are "if ‘fix_issue_010’ is present in the supplied options then drop all elements with v:fix_issue_010=false", then you might use a stylesheet like this:

    <xsl:transform version="3.0" 
    xmlns:v="http://my-versioning-namespace/"
    xmlns:xsl="http://www.w3.org/2001/XSL/Transform">
    
    <xsl:param name="options" as="xs:string*"/>
    
    <xsl:mode on-no-match="shallow-copy"/>
    
    <xsl:template match="*[@v:*[.='false' and local-name()=$options]]"/>
    <xsl:template match="@v:*"/>
    </xsl:transform>
    

    The xsl:mode says copy everything by default; the first xsl:template says drop elements having an attribute in the v namespace whose local name equals one of the supplied options and whose value is ‘false’; the second xsl:template says drop all attributes in the v namespace.

    That might not be exactly the rules you want to apply, of course.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search