Skip Ribbon Commands
Skip to main content

Robin | zevenseas | SharePoint Blog

:

The zevenseas Community > Blogs > Robin | zevenseas | SharePoint Blog > Posts > Adding Themes the supported way!
August 02
Adding Themes the supported way!

Yes! I’ve created a solution that allows you to add a theme the supported way, meaning that you don’t have to overwrite the default SPThemes.XML that resides in the LAYOUTS folder. The only thing you have to do is add the Theme to the THEMES folder and add your own custom SPThemes.XML somewhere in the 12 hive (a folder in the FEATURES folder could be a good example) and add this path to my solution and you’re done ;)

You might wonder how I’m achieving this.. Well I’ve created a custom .aspx page that lets you choose a theme, based on the out-of-the-box one but unlike the out-of-the-box one that only loads the SPThemes.XML file. I’ve chosen to load several XML files. Yes.. the themeweb.aspx page only loads a XML file.. it’s not getting the collection of themes out of the SPFarm or SPWebApplication object like I thought it was stored in SharePoint. The class SPThemes is just a DataSet.

So with a simple HideCustomAction and CustomAction element in my feature elements file. I can hide the original link to the theme select page and display my own theme selector page.

To add those XML files, I’ve created YAAP (Yet Another Application Page) in Central Administration to define the paths like so:

image

Then, next to adding custom themes, there’s also an option to hide certain themes from a particular WebApplication (just like my FeatureBlocker tool does with Features)

image

So when opening the Theme Selection page on a web or a site it looks like this: (compare the available themes with the screenshot above)

image

Pretty cool eh? ;)

So how does it look like behind the scenes? Well, I’ve used the same source as much as possible that MS used to created the page and added a couple and replaced a couple of things.

To get all the XML files, instead of loading just one I’ve used this

string filePath = String.Format("{0}\\LAYOUTS\\{1}\\SPThemes.xml", 
    SPUtility.GetGenericSetupPath("TEMPLATE"), 
    base.Web.Language.ToString(CultureInfo.InvariantCulture));
this.dsSPThemes = new SPThemes();
this.dsSPThemes.DataSetName = "SPThemes";
this.dsSPThemes.Locale = new CultureInfo("en-US");
this.dsSPThemes.Namespace = "http://tempuri.org/SPThemes.xsd";
this.dsSPThemes.ReadXml(filePath);
DataView view = FilterThemes(this.dsSPThemes.Tables[0]);
view.Sort = "DisplayName";
this.lstTemplates.DataSource = view;
this.lstTemplates.DataBind();

 

private DataView FilterThemes(DataTable dataTable)
{
    DataTable themesTable = new DataTable();
    themesTable = dataTable.Clone();
    //Getting the custom .xml themes and load them
    filePaths = GetOtherXmlDefinitions();
    themesTable = ProcessOtherXmlDefinitions(themesTable);
    //Getting the blocked themes
    List<string> templateIds = new List<string>();

SPWebApplication webApplication =

SPWebApplication.Lookup(SPContext.Current.Site.WebApplication.GetResponseUri(SPUrlZone.Default));

    Themes themeCollection = webApplication.GetChild<Themes>("ThemeCollection");
    if (themeCollection != null)
    {
        templateIds = themeCollection.TemplateIDs;
    }
    foreach (DataRow row in dataTable.Rows)
    {
        bool isBlocked = false;
        foreach (string templateId in templateIds)
        {
            if (row["TemplateID"].ToString() == templateId)
            {
                isBlocked = true;
                break;
            }
        }
        if (!isBlocked)
        {
            DataRow themeRow = themesTable.NewRow();
            themeRow.ItemArray = row.ItemArray;
            themesTable.Rows.Add(themeRow);
        }                
    }
    return (new DataView(themesTable));
}
private List<string> GetOtherXmlDefinitions()
{
    SPFarm farm = SPFarm.Local;

ThemesXmlFileLocations themeFileLocations =

farm.GetChild<ThemesXmlFileLocations>("ThemesXmlFileLocations");

    if (themeFileLocations != null)
    {
        filePaths = new List<string>();
        filePaths = themeFileLocations.FilePaths;                
    }
    return filePaths;
}
private DataTable ProcessOtherXmlDefinitions(DataTable dataTable)
{
    if (filePaths.Count > 0)
    {
        foreach (string filePath in filePaths)
        {
            if (!string.IsNullOrEmpty(filePath))
            {
                string customFilePath = SPUtility.GetGenericSetupPath(filePath);
                SPThemes spThemes = new SPThemes();
                spThemes.DataSetName = "SPThemes";
                spThemes.Locale = new CultureInfo("en-US");
                spThemes.Namespace = "http://tempuri.org/SPThemes.xsd";
                spThemes.ReadXml(customFilePath);
                foreach (DataRow row in spThemes.Tables[0].Rows)
                {
                    DataRow customThemeRow = dataTable.NewRow();
                    customThemeRow.ItemArray = row.ItemArray;
                    dataTable.Rows.Add(customThemeRow);
                }
            }
        }
    }
    return dataTable;
}

And there you have it.. let me know what you think! And yes.. It will be on CodePlex very shortly ;)  Get it from CodePlex here!

 

Technorati Tags:

Comments

Tobias Zimmergren

Looking sweet mate.
System Account on 03/08/2009 00:39

Brad Saide

Hell yeah! That's a great idea!

I'm looking forward to seeing it on CodePlex...

Brad
System Account on 13/08/2009 06:16

Brad

Hi Robin.

It looks like the code has been pulled from CodePlex - This page is the only location where the info still exists.

Is it going to be re-released soon?
Thanks!
Brad
System Account on 07/01/2010 21:12
 

 Statistics

 
Views: 4200
Comments: 3
Tags:
Published:1416 Days Ago