Declaratively create Composed Looks in SharePoint 2013 with elements.xml
This is really a follow-up to my earlier post about tips with SharePoint publishing customisations. Composed looks have been a part of a couple of projects recently. In the first, a solution for on-premise, we used code in a feature receiver to add a number of items to the Composed Looks list. In the second, for Office 365, a bit of research offered an alternative approach with no code.
What are Composed Looks
A composed look is a collection of master page, colour scheme file, font scheme file and background image. There is a site list called Composed Looks that holds them, and they are shown in the Change the Look page as the thumbnail options you can choose to apply branding in one hit.
In order to get your new composed look working there are a few gotchas you need to know:
- When you specify a master page in your composed look, there must be a valid .preview file with the same name. This file defines the thumbnail image – if you look at an existing file (such as seattle.preview or olso.preview) you will find html and styling rules, along with some clever token replacement that references colours in the color scheme file.
- A composed look must have a master page and colour scheme (.spcolor) file, but font scheme and background image are optional.
- When using sites and site collections, files are split between local and root gallery locations:
- The Composed look List is local to the site – it doesn’t inherit from the parent site.
- Master pages go in the site Master Page Gallery.
- Spcolor, sptheme and image files go in the site collection master page gallery.
If any of the files you specify in your composed look don’t exist (or you get the url wrong), the thumbnail won’t display. If any of the files in your composed look are invalid, the thumbnail won’t display. If your master page exists but has no .preview file, the thumbnail won’t display. Diligence is important!
Adding Composed Looks using Elements.xml
In researching whether this was indeed possible, I came across an article by Tom Daly. All credit should go to him – I’ve simply tidied up a bit around his work. I already knoew that it was possible to create lists as part of a feature using only the elements.xml, and to place items in that new list. I hadn’t realised that adding items to an existing list also works.
In Visual Studio 2013 the process is easy – simply add a new item to your project, and in the Add New Item dialog select Office/SharePoint in the left column and Empty Element in the right. Visual Studio will create the new element with an Elements.xml ready and waiting for you.
To create our composed looks we simply edit that elements.xml file.
First we need to reference our list. As per Tom’s post, we need to add a ListInstance element to our file:
<ListInstance FeatureId="{00000000-0000-0000-0000-000000000000}" TemplateType="124" Title="Composed Looks" Url="_catalogs/design" RootWebOnly="FALSE"> </ListInstance>
That xml points to our existing list, and the url is a relative path so will reference the list in the current site for our feature, which is what we want.
Now we need to add at least one item. To do that we need to add Data and Rows elements to hold however many Row elements we have items:
<ListInstance FeatureId="{00000000-0000-0000-0000-000000000000}" TemplateType="124" Title="Composed Looks" Url="_catalogs/design" RootWebOnly="FALSE"> <Data> <Rows> </Rows> </Data> </ListInstance>
Then we add the following code for a single composed look:
<Row> <Field Name="ContentTypeId">0x0060A82B9F5D2F6A44A6A5723277B06731</Field> <Field Name="Title">My Composed Look</Field> <Field Name="_ModerationStatus">0</Field> <Field Name="FSObjType">0</Field> <Field Name="Name">My Composed Look</Field> <Field Name="MasterPageUrl">~site/_catalogs/masterpage/MyMasterPage.master, ~site/_catalogs/masterpage/MymasterPage.master</Field> <Field Name="ThemeUrl">~sitecollection/_catalogs/theme/15/MyColorTheme.spcolor, ~sitecollection/_catalogs/theme/15/MyColorTheme.spcolor</Field> <Field Name="ImageUrl"></Field> <Field Name="FontSchemeUrl"></Field> <Field Name="DisplayOrder">1</Field> </Row>
There are two parts to the url fields – before the comma is the path to the file and after the comma is the description shown in the list dialog. I set both to the same, but the description could be something more meaningful if you like.
Note that the master page url uses ~site in the path, whilst the theme url uses ~sitecollection. Both of these will be replaced by SharePoint with the correct paths for the current site or site collection.
Note also that I have only specified master page and colour theme. The other two are optional, and SharePoint will use the default font scheme and no background image, respectively. The colour theme would appear to be mandatory because it is used in generating the thumbnail image in conjunction with the .preview file.
The DisplayOrder field affects where in the list of thumbnails our composed look appears. The out-of-the-box SharePoint themes start at 10 and the current theme is always 0. If more than one item has the same DisplayOrder they are displayed in the same order as in the composed looks list. Since I want my customisations to appear first I usually stick a value of 1 in there.
I have removed a couple of fields from the list that Tom specified, most notably the ID field, which SharePoint will generate a value for and (I believe) should be unique, so better to let it deal with that than potentially muck things up ourselves.
Deploying the Composed Look
Once we’ve created our elements.xml, getting the items deployed to our list is easy – simply create a feature and add that module to it. There are a few things I want to mention here:
- Tom suggests that the declarative approach does not create items more than once if a feature is reactivated. I have not found this to be the case – deactivate and reactivate the feature and you will end up with duplicate items. Not terrible, but worth knowing.
- You need a site level feature to add items to the composed looks list. As some of the things that list item references are at a site collection level, I suggest the following feature and module structure:
- Site Collection Feature
- Module: Theme files, containing .spcolor, .spfont and background image files. Deploys to _catalogs/Theme/15 folder.
- Module: Stylesheets. Deploys to Style Library/Themable folder or a subfolder thereof.
- Module: CSS Images. Deploys to Style Library/Themable folder or a subfolder thereof. Separating images referenced by my CSS is a personal preference as I like tidy VS projects!
- If you have web parts or search display templates I would put those in the site collection feature as well.
- Site Feature
- Module: Master pages. Contains .master and associated .preview files. Deploys to _catalogs/masterpage folder.
- Module: Page layouts. Contains .aspx layout files. Deploys to _catalogs/masterpage folder.
- Module: Composed Looks: Contains the list items in our elements.xml file. Deploys to Composed Looks list.
- Site Collection Feature