Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Conditional Compile" in XAML?

Tags:

wpf

xaml

We have a program we use internally to test and validate an industrial control product we sell. We'd like to be able to offer a scaled-down or lightweight version of this to certain customers.

Our program is written in using C# and WPF (thus XAML). Having sections of C# code that only build for use in our factory is easily done using conditional compile features, e.g.,

#if FACTORY
    // our in-house code . . .  
   . . . 
   . . . 
#endif

But how can we accomplish something similar for the XAML portion of our program?

Note: **There's a Stack Overflow question on this topic where someone posted a terse answer with a link but the link doesn't seem to be related to the question. So don't count this as a duplicate based on that because that doesn't answer the question.* XAML Conditional Compilation

like image 969
user316117 Avatar asked Feb 07 '14 21:02

user316117


3 Answers

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.

like image 195
slugster Avatar answered Oct 22 '22 06:10

slugster


I'd use an XSTL transformation, this MSDN article explains how to apply them at compile time. It should be possible to set up the transform to strip sections inside pre-processor tags (this SO question appears to show just that), although I'd probably put them in comments myself so that you don't break the Visual Studio designer. There's also this SO question which shows how to include processor directives as regular XML tags that you could again just embed inside your XAML.

like image 34
Mark Feldman Avatar answered Oct 22 '22 06:10

Mark Feldman


  1. Define compiler constant FACTORY.

  2. Create markup extension class:

    using System;
    using System.Windows.Markup;
    
    namespace Conditional 
    {
        public class Condition : MarkupExtension 
        {
            public object MyFactory { get; set; }
            public object Other { get; set; }
    
            public override object ProvideValue(IServiceProvider sp) 
            {
            #if FACTORY
                return this.MyFactory;
            #else
                return this.Other;
            #endif
            }
        }
    }
    
  3. In XAML markup:

    • Import namespace:
    xmlns:conditional="clr-namespace:RootNamespace.Conditional"
    
    • Insert this block of code where need conditional XAML markup:
    <ViewBox>
        <conditional:Condition>
            <conditional:Condition.MyFactory>
                <TextBlock Text="This is My Factory"/>
            </conditional:Condition.MyFactory>
            <conditional:Condition.Other>
                <TextBlock Text="this is other" />
            </conditional:Condition.Other>
        </conditional:Condition>
    </ViewBox>
    
like image 1
Aave Avatar answered Oct 22 '22 05:10

Aave