Developing for Modern Windows

Tips, tricks, and guides for developing on modern Windows platforms

Multi-Branded Apps in Visual Studio (Windows 10 UWP)

Follow the techniques in this article to build multiple branded apps (e.g. several sports apps for different teams) from a single Visual Studio solution.

What will we Do?

In this tutorial I’ll show you three techniques for creating a multi-branded app by taking you step-by-step through building an app with two different brandings, which you can switch between easily.

Three Techniques

  1. Create separate build configurations for each brand.
  2. Separate code for each brand using #if Brand directives.
  3. Use pre-build commands to move files around.

Our example app will have two brands: BatBrand and SuperBrand. Each brand will have its own live tiles and splash screen, and a few unique colour and string resources.

Before you Start

This example uses the Windows 10 UWP and Visual Studio 2015, however there is nothing here unique to Windows 10, so the same steps should work for other targets, though some details may differ.

 

Visual Studio 2015 and Windows 10 are both pre-release at the time of writing this, so some minor things may change before their final releases.

Assets Download

Download the pre-prepared live time and splash screen images for the two brands you’ll create (or create your own):

Create a New App

In Visual Studio 2015, create a new Windows Universal app with the Blank App (Windows Universal) template:

  1. File > New Project.
  2. Choose the Windows Universal templates folder.
  3. Select the Blank App (Windows Universal) template.
  4. Name your app and choose a location to save it.
  5. Click OK.

Create Branded Build Configurations

You need a build configuration for each brand. This is the heart of the branding, as the other steps work by checking which brand’s build configuration is active.

Use the following steps to create a build configuration. This example project uses two brands, BatBrand and SuperBrand. We’ll create BatBrand first.

Go to Build > Configuration Manager in the main menu:

  1. From the Active Solution Configuration drop-down choose <New…>

  1. Type BatBrand in the Name: field.

 

You need to name things carefully as later steps refer to the build by this name.

  1. In the Copy Settings From: drop-down, choose Release.
We are creating our branded builds as Release builds. You may want to create separate Debug builds as well, but for this example that’s overkill.
  1. Leave Create new project configurations ticked.
  2. Click OK.

Close the Configuration Manager window.

Create a Conditional Compiler Symbol for your Build Configuration

You’ve created a “BatBrand” build configuration. Now to reference this configuration in code (so you can include certain code only when BatBuild is current), add a conditional compiler symbol:


  1. Right-click your project in Solution Explorer and choose Properties.

  1. Choose the Build tab on the left.
  2. Select Active (BatBrand) in the Configuration: field at the top of the window.
  3. In the Conditional compiler symbols: field, add “BatBrand” (separate it from the existing symbols with a semi-colon).

Save the file, then repeat all those steps to create the “SuperBrand” configuration.

Separate your Brand Files

Next you need a folder to hold the different brand files in. We will later use this to copy the files for the current brand into the project.

Create a Branding subfolder in your solution:


1. Right-click the project, choose Add > New Folder, and name it Branding.

Using the same method create two sub-folders within Branding: BatBrand and SuperBrand.

It’s important for the brand folder names to match their build configuration names because of how we will reference them later.

Create subfolders within each brand’s folder called Assets. This will be store the live tiles/splash screens for each brand.

Your solution should look now like this:

 branding_2Add the Image Assets

Each brand needs its own live tiles and splash screens. Copy the images from the BrandingAssets download into the relevant Assets folders for each brand or create your own assets. We’ll do more with these assets later.

Create Brand-Specific Files

Make copies of the following files in each of the branded folders:

  • AssemblyInfo.cs
  • Package.appxmanifest

AssemblyInfo.cs

This file holds the assembly title, version, and so on. You need a separate one for each app, and you need to customise them. I’ll show you what to do with the BatBrand version, then you can repeat the steps for SuperBrand.

  1. Open the copy of AssemblyInfo.cs in the BatBrand folder.
  2. Replace the entire contents of the file with the following code:

 

#if BatBrand
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

//General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BatBrandApp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BatBrandApp")]
[assembly: AssemblyCopyright("Copyright ©  2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Version information for an assembly consists of the following four values:
//      Major Version
//      Minor Version
//      Build Number
//      Revision

// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]
#endif

The most important change is wrapped the entire file in #if BatBrand and #endif. This means that the code is only compiled when the BatBrand build configuration is active.

I also changed the AssemblyTitle and AssemplyProduct properties to match the branding.

Repeat the above steps to modify the copy of AssemblyInfo.cs in the SuperBrand folder.

 One Last Thing with AssemblyInfo.cs

You can only have one active copy of this file in your project, but the original is still there (so if you have BatBrand’s build selected you will have the BatBrand copy set to compile as well as the original copy). For simplicity, comment out the original file. In a proper project you might be more sophisticated and keep it around for non-branded builds (e.g. you could use #if !BatBuild && !SuperBuild) or #if NonBranded).

Package.appxmanifest

Because you can only have one copy of Package.appxmanifest, and because you can’t use conditional compiler symbols in XML, we have to use a trick here. Set your Package.appxmanifest branded copies to a compile type of None:

  1. Select the file in the Solution Explorer.
  2. Change the Build Action property to None.
Do NOT do this for the original copy in the root project folder.

When we copy a branded version of this file over the original, the copy will be given the original file’s properties, including its build action. So only the copy of the file in the root folder gets compiled, but we can always keep multiple branded versions that replace the root folder version when we do a build.

Modify the Manifest

I’ll leave you to modify the app manifest for each brand in much the same way you modified AssemblyInfo.cs. The manifest will modify how the app is named, among other things. Don’t touch the images, as we will automate that part later.

Package.appxmanifest contains information about the app package. It is updated when you build a new version, and it contains your package’s ID (for the store), so you should copy this back to the brand folder whenever changes are made to it. You could automate this by adding a copy command to the Post-build actions to copy the current copy back over the brand’s original copy, and therefore copying over any changes made since you copied the branded version into the main project.
The current (pre-release) build of Visual Studio has a bug that prevents editing Package.appxmanufest in the manifest editor. If you are affected by this bug you can make changes directly to the XML code.

Resource Dictionary

We’ll create a resource dictionary to hold a couple of strings and colour resources for each brand.

Create a new resource dictionary:

  1. Right-click the project in Solution Explorer
  2. Choose Add > New Item
  3. Choose Resource Dictionary
  4. Call the new file BrandingStyles.xaml
  5. Click Add.

Open the new file and replace its contents with the following code:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Input">

    <SolidColorBrush x:Key="MainColour">#FFFFFFFF</Color>
    <SolidColorBrush x:Key="SecondaryColour">#FF000000</Color>
    <x:String x:Key="AppTitle">App for a Brand</x:String>
    <x:String x:Key="Message">Message for this Brand</x:String>
</ResourceDictionary>

That is just a couple of colours and strings that we can personalise for each brand.

Duplicate BrandingStyles.xaml file in each of the brand folders so they have their own copy.

Now customise the colour properties and strings for each brand’s copy of the file. Here are the values for each brand:

BatBrand

MainColor: #FF2A2A2A

SecondaryColor: #FFFFE651

AppTitle: Holy Bat Branded App!

Message: Welcome to my bat-tastic app!

 

SuperBrand

MainColor: #FFE94B44

SecondaryColor: #FF4F7CCB

AppTitle: Super App!

Message: Welcome to my super app!

Reference the Resource Dictionary

Replace all the code in App.xaml with the code below:

<Application
    x:Class="BrandingDemo.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:BrandingDemo"
    RequestedTheme="Light">

    <Application.Resources>
        <ResourceDictionary Source="BrandingStyles.xaml" />
    </Application.Resources>
</Application>

Now whichever copy of BrandingStyles is currently in the root folder will be used at runtime (we’ll copy the relevant version at build time).

Pre-build commands

The final step is to create pre-build commands to copy the branded files into the main project based on the selected build configuration.

We need to add several pre-build commands to copy the following files from the relevant brand folder:

  • All images in the Assets folder
  • Package.appxmanifest
  • BrandingStyles.xaml

 

 You don’t need to copy the AssemblyInfo.cs file because the #if Brand directives take care of which code is compiled.

Right-click the project name in Solution Explorer, then choose Properties.

  1. Select the Build Events tab.
  2. Enter the following code into the Pre-build event command line: text area (copy it carefully!):
copy "$(projectdir)Branding\$(ConfigurationName)\Package.appxmanifest" "$(projectdir)Package.appxmanifest" /Y
copy "$(projectdir)Branding\$(ConfigurationName)\Assets\*.*" "$(projectdir)Assets\*.*" /Y
copy "$(projectdir)Branding\$(ConfigurationName)\BrandingStyles.xaml" "$(projectdir)BrandingStyles.xaml" /Y

 

 Click Edit Pre-build if you want a more spacious area for typing.

Explanation

Pre-build commands use macro shortcuts, and we use the following:

$(projectdir) – this represents the root folder of the project

$(ConfigurationName) – this represents the name of the current build configuration.

The “/Y” automatically agrees to any confirmations, such as overwriting an existing file.

These commands are executed at build time. Selecting a particular brand’s build configuration does not automatically run the pre-build steps, so you should do a build whenever changing brands to ensure the relevant files are copied across.

Create the App

Let’s add some basic app UI so you can see the branding in action. Paste the following XAML into MainPage.xaml (replace the whole contents). It uses the resources set up in BrandingStyles.xaml to display some very basic UI:

<Page
   x:Class="BrandingDemo.MainPage"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local="using:BrandingDemo"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   mc:Ignorable="d">

   <Grid Background="{StaticResource MainColour}">
       <StackPanel>
            <TextBlock Foreground="{StaticResource SecondaryColour}" Text="{StaticResource AppTitle}"&gt;&lt;/TextBlock>
            <TextBlock Foreground="{StaticResource SecondaryColour}" Text="{StaticResource Message}"></TextBlock>
       </StackPanel>
    </Grid>
</Page>

All Done

That’s everything. You’ve created brand-specific build configurations, separated code by brand using #if Brand directives, and created separate files for brands, that you move around via pre-build commands. You’ve also created brand-specific tile and splash screen images and a separate resource dictionary for each brand to customise colours and strings.

Now it’s time to test it. Choose a brand and launch the app. If all goes well it will have the correct tile image, splash screen, colours, strings, etc. Then switch to the other brand and rebuild the app. Everything should now be switched to the new brand. Voila!

Notes

If you make changes to the files in the root project folder and then rebuild, the unchanged branded copies will copy back over the changed versions! You shouldn’t need to change the branded files often, but make sure to change the copies in the brand folders and then do a rebuild to copy them across.

You could always be more sophisticated with pre- and post-build commands. There is more information available in the documentation: Build Commands documentation.

You can use #if Brand type compiler directives anywhere in your code, but I’d recommend only using them at the file level (like in the AssemblyInfo.cs example above where you have a copy of a file for each brand). Otherwise you’ll end up with messy code. If you need separate code for each brand, create a custom class for each, in its own file.

Tags:

4 Responses to “Multi-Branded Apps in Visual Studio (Windows 10 UWP)”

  1. Anonymous says:

    A great article for multiple build configuration using same solution. Really helpful

  2. Me says:

    Thanks, exactly what is was looking for. I had to rename the other appxmanifest files to appxmanifest2 though since VS did not allow having multiple appxmanifest files.

  3. Viktor says:

    This is awesome!

    I was shocked when I figured out that Visual Studio had no possibility to just add another build-target with it’s own configuration automatically.

Leave a Reply

Your email address will not be published.