I had a similar requirement once. In my case they wanted users to be able to change the "color layout" of a MOSS portal (so the layout and fonts was the same, but background color and colors of images were different in each theme). I created a "base theme" which included a complete layout (one of the provided themes) as a single CSS file. Then I created additional themes, such as "blue.css", "red.css", "green.css" et cetera and put all those files in portal/ourthemes/
.
We wanted the users to be able to choose their theme, so we created a new user profile property "CurrentTheme" (Sharepoint Central Administration -> Shared services -> User profiles and properties -> Add profile property) which was defined as string with a pre-defined list of choices.
Then I created a simple ASP.Net control which rendered as
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Dim oProf As Microsoft.Office.Server.UserProfiles.UserProfile = Microsoft.Office.Server.UserProfiles.ProfileLoader.GetProfileLoader.GetUserProfile()
Dim UserTheme As String
Try
If oProf.Item("CurrentTheme") IsNot Nothing Then
UserTheme = oProf.Item("CurrentTheme").Value.ToString()
Else
UserTheme = "blue"
End If
Catch ex As Exception
'shouldn't fail if we don't know the value
UserTheme = "blue" 'a default value for users who dont have a theme yet
End Try
writer.WriteLine("<link rel='stylesheet' type='text/css' href='/portal/ourthemess" & Trim(UserTheme) & ".css' />")
End Sub
(Disclaimer: the actual code was a bit longer, because we used caching per-user to avoid reading the property from UserProfile
every time user loaded the page)
Then I put this control in the master page created for that portal.
EDIT: To do the caching, we created a cache key which contained user name and stored the generated text in there. The result was something like this:
Dim KeyName As String = Page.User.Identity.Name & "_CurrentTheme"
If (Not Me.Page.Cache.Item(KeyName) Is Nothing) Then
writer.Write(Page.Cache.Item(KeyName).ToString)
Else
'...code posted previously goes in here
'at the end
Me.Page.Cache.Add(KeyName, _
AllContentRenderedInPreviousCodeAsString, _
Nothing, _
Caching.Cache.NoAbsoluteExpiration, _
Caching.Cache.NoSlidingExpiration, _
Caching.CacheItemPriority.Low, Nothing)
End If
Best Answer
If you want to make them reusable across the site collection for each user you can add Fields to the User Information List. You can add a feature receiver to your web parts solution that can create this column or check to see if this column exists in the User information list to be sure that the Column exists.
The User Information list is a Standard SharePoint list that SharePoint uses to store user information. To access the User Information List you can go to the Root web of the Site Collection and use the SiteUserInfoList property
E.G.
To access a users List Item you can use the Users Id to get the ListItem back from the User Information List
E.G.
If you are using MOSS you can store this information in the User Profiles and make it available across Site Collections this does not need My Sites to be enabled. You would need to use the User Profile classes to access this.