Extending Personal Web Site (6): Dynamic themes (1 of 2)

Source code download

This web site has three themes.  By clicking "Change Theme" radio button on the top left corner the web site will "change cloth" to a new look. I am not a graphic designer so I just did the best I can using Photoshop come up with these themes on my own. By far I know there are two way to accomplish this in ASP.NET 2.0. One is using different master file for each theme, another one is using the same master file and load theme on the fly. I will show you step by step for the second option. This section is about the code, next section will be tips and tricks dealing with multiple themes including but not limit to CSS, graphic design and page layout concern.


Step 1: Under App_Code folder, we add a class name Theme.cs:



public class Theme
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}


public Theme(string name)
{
Name = name;
}
}


Step 2: Under App_Code folder, we add a ThemeManager class name ThemeManager.cs



using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections;
using System.Collections.Generic;
using System.IO;
public class ThemeManager
{
#region Theme-Related Method
public static List<Theme> GetThemes()
{
DirectoryInfo dInfo = new DirectoryInfo(System.Web.HttpContext.Current.Server.MapPath("App_Themes"));
DirectoryInfo[] dArrInfo = dInfo.GetDirectories();
List<Theme> list = new List<Theme>();
foreach (DirectoryInfo sDirectory in dArrInfo)
{
Theme temp = new Theme(sDirectory.Name);
list.Add(temp);
}
return list;
}
#endregion
}


Step 3: Comment out <!--<pages styleSheetTheme="Black"/>--> in web.config


Step  4: In Default.master page Add datasource and radiobutton list. You can use dropdownlist if you would preferred.



<asp:ObjectDataSource ID="ThemeDataSource" runat="server" SelectMethod="GetThemes" TypeName="ThemeManager" ></asp:ObjectDataSource>


<asp:RadioButtonList ID="strTheme" runat="server" DataTextField=name DataValueField=name OnSelectedIndexChanged="strTheme_SelectedIndexChanged" OnDataBound="strTheme_DataBound" DataSourceID="ThemeDataSource" AutoPostBack=true RepeatDirection=Horizontal />


Step 5: In Default.master.cs add these methods



protected void strTheme_DataBound(object sender, EventArgs e)
{
strTheme.SelectedValue = Page.Theme;
}
protected void strTheme_SelectedIndexChanged(object sender, EventArgs e)
{
Session.Add("MyTheme", strTheme.SelectedValue);
Server.Transfer(Request.FilePath);
}


Step 6: Add BasePage class under App_Code



using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;


public class BasePage : System.Web.UI.Page
{
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
if (Session["MyTheme"] == null)
{
Session.Add("MyTheme", "Yellow");
Page.Theme = ((string)Session["MyTheme"]);
}
else
{
Page.Theme = ((string)Session["MyTheme"]);
}
}
}


Step 7: Inherit BasePage from all pages using dynamic theme



public partial class Default_aspx : BasePage{
}

Back to the top

Add comment
*Name:
Website:
*Comments:

Due to the amount of spam, new posts are subject for approval.


Back to the top
Comments
01/02/2008 by Ata K. S.
Good Solution, tanx and happy new year

12/13/2006 by John Hughes
Could it be the ~/ before App_Themes?

Dim dInfo As New DirectoryInfo(System.Web.HttpContext.Current.Server.MapPath("~/App_Themes"))

11/30/2006 by jon
Maybe i'm missing something but im getting an error on the manage pages unless i copy the theme folder to admin directory. I was just curious on how you sloved this problem on your site.

"DirectoryInfo dInfo = new DirectoryInfo(System.Web.HttpContext.Current.Server.MapPath("App_Themes"));"




11/08/2006 by bobd
I would like to continue with the discussion that Christopher Simmons started.

How do you determine if a postback has been caused by the theme selector's dropdownlist from the App_Theme directory?

Right now I have:

Imports System.Web.UI.Page
Public Class BasePage
Inherits System.Web.UI.Page

Protected Overrides Sub OnPreInit(ByVal e As System.EventArgs)
Dim preferredTheme As New Profile("PreferredTheme")
Me.Theme = preferredTheme.Name
MyBase.OnPreInit(e)
End Sub
End Class

I know that Me.Theme is being set every time.


08/24/2006 by Naanu

base.OnPreInit(e);

should be called after the theme as been set.

08/04/2006 by Sue
My bad :-) Step 6 please change "Yellow" to "White", or whatever theme available in the directory you want to use it as default theme.

08/04/2006 by cool
Theme Yellow cannot be found in the application or global theme directories. CAn u tell em wht might be the problem

07/26/2006 by John Hughes
For pooja in VB.net

I used the translator as suggested by Martin but I am neither a C# programmer or a vb.net programmer for that matter so using the translator was not so easy: http://authors.aspalliance.com/aldotnet/examples/translate.aspx

This is Sue's method translated

Step 1: Under App_Code folder, we add a class name Theme.vb:
I had trouble with ‘name’ and ‘Name’ so I decided to call ‘name’ ‘LittleName’ and this seemed to do the trick.
Imports Microsoft.VisualBasic

Public Class Theme
Private _name As String

Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property

Public Sub New(ByVal LittleName As String)
Name = LittleName
End Sub 'New
End Class 'Theme
Step 2: Under App_Code folder, we add a ThemeManager class name ThemeManager.vb
List caused a problem. The equivalent seems to be List(Of Theme)
I had to remove ‘#region Theme-Related Method’ and the closing statement’#endregion’ to make the translator work without error
I latter had to add ~/ to App_Themes to get the correct path for sub directories of the web root.
Imports Microsoft.VisualBasic
Imports System
Imports System.Data
Imports System.Configuration
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls
Imports System.Collections
Imports System.Collections.Generic
Imports System.io
Imports System.Windows.Forms

Public Class ThemeManager
Public Shared Function GetThemes() As List(Of Theme)
Dim dInfo As New DirectoryInfo(System.Web.HttpContext.Current.Server.MapPath("~/App_Themes"))
Dim dArrInfo As DirectoryInfo() = dInfo.GetDirectories()
Dim list As New List(Of Theme)
Dim sDirectory As DirectoryInfo
For Each sDirectory In dArrInfo
Dim temp As New Theme(sDirectory.Name)
list.Add(temp)
Next sDirectory
Return list
End Function 'GetThemes

End Class
Step 3: Comment out in web.config
Note if you want your pages in the IDE to appear in Document view with an applied theme whilst you are editing you will temporarily need restore this line in web.config and remember to comment it out when you upload the web.config

Step 4: In Default.master page Add datasource and radiobutton list. You can use dropdownlist if you would preferred.




Step 5: In Default.master.vb add these methods
Partial Class Default_master
Inherits System.Web.UI.MasterPage

Protected Sub strTheme_DataBound(ByVal sender As Object, ByVal e As EventArgs)
strTheme.SelectedValue = Page.Theme
End Sub 'strTheme_DataBound

Protected Sub strTheme_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
Session.Add("MyTheme", strTheme.SelectedValue)
Server.Transfer(Request.FilePath)
End Sub 'strTheme_SelectedIndexChanged
End Class

Step 6: Add BasePage class under App_Code
Imports Microsoft.VisualBasic
Imports System
Imports System.Data
Imports System.Configuration
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls

Public Class BasePage
Inherits System.Web.UI.Page

Protected Overrides Sub OnPreInit(ByVal e As EventArgs)
MyBase.OnPreInit(e)
If Session("MyTheme") Is Nothing Then
Session.Add("MyTheme", "Black") ‘ Whatever theme you want as default
Page.Theme = CStr(Session("MyTheme"))
Else
Page.Theme = CStr(Session("MyTheme"))
End If
End Sub 'OnPreInit
End Class 'BasePage

Step 7: Inherit BasePage from all pages using dynamic theme
i.e Default.aspx.vb would become.

Partial Class Default_aspx
Inherits BasePage
‘**** instead of (Inherits System.Web.UI.Page) which is now in BasePage.vb I was not sure what the 'partial' translated as so dropped it out. This works for me!

Public Sub Randomize(ByVal sender As Object, ByVal e As EventArgs)
Dim r As Random = New Random
FormView1.PageIndex = r.Next(FormView1.PageCount)
End Sub

End Class

If I can make this work, anyone can!




07/24/2006 by pooja
I was trying to add different themes as done by Sue.
But i am using VB.net instead of C# ,

i could not follow step # 2

Anybody who can help me out ?

thanks

07/14/2006 by Chris Smith
Chris, I agree that in a situation where you want to enable users to maintain their theme choice, profiles are best (custom or MS default). If you allow your users to customize the heck out of your site (web parts, different master pages with pure CSS layouts, etc), storing it somewhere would be almost manditory, lest you anger your users the next time the hit your site.

Sue's example is a good example of a temporary way for users to customize their experience, since it's not storing the data in a dataset or writing it to a cookie or somesuch. This session-based approach might be a good idea if you wanted to create an alternate version of your site for visibility purposes, or just because.

In the end, which implementation depends on your reason for allowing the changing of themes.

07/14/2006 by tt
i see

07/13/2006 by Stephen
"This might be off the subject but how do you set your ccs to be Mozilla Firefox friendly? Everytime I render my site with Firefox, it is not render the same as IE 6."

If that is where you are starting with differences between CSS in IE and FF, then you have a long long loooong way to go...

One item of things to look for:
- differences in the way both browsers handle padding and magin

07/13/2006 by Christopher Simmons
Here's how i implemented it in vb.net using profile services does anyone agree that sues implementation using sessions isn't a good idea for a high usage website?

Protected Overrides Sub OnPreInit(ByVal e As EventArgs)
Dim pro As New PCommon


' if this is a postback caused by the theme selector's dropdownlist, retrieve
' the selected theme and use it for the current page request

' if not a postback, or a postback caused by controls other then the theme selector,
' set the page's theme with the value found in the user's profile, if present
Me.Theme = pro.Theme

MyBase.OnPreInit(e)
End Sub


Public Class PCommon

Public Property Theme()
Get
Return HttpContext.Current.Profile.GetPropertyValue("Theme")
End Get
Set(ByVal value)
HttpContext.Current.Profile.SetPropertyValue("Theme", value)
End Set
End Property
End Class


Private Sub ChangeColor(ByVal ColorID As Integer)
Dim pro As New PCommon

Select Case ColorID
Case 1
pro.Theme = "Corporate"












07/13/2006 by Stephen
Nice to see some of your work get linked right off the ASP.NET website :-)

07/07/2006 by pinki
i have followed the same as u said but when i checking the radio button the color is not changing. plz let em know what might be the problem

06/23/2006 by Martin
lecylg:

Just go to : http://authors.aspalliance.com/aldotnet/examples/translate.aspx

It's almost too easy ;-)

05/07/2006 by lecylg
is there a vb version of this class? thank you

03/15/2006 by James

Hi


I have sorted myself.


I had put outside the { } of the


public partial class Default_master : System.Web.UI.MasterPage


I have put inside and all seems ok now


Cheers for the tutorial


James



03/15/2006 by James

Hi


I have followed the above procedure, but I am having problems.


I get two errors when trying to compile the site. Both are


Error 2 Expected class, delegate, enum, interface, or struct 


and they refer to the code added to the master.cs


Can you help. Have I missed anything?


Cheers


James


 



03/15/2006 by Sue

Caleb,


If you are new to programming. Master page will be a place to start. yes you can use dynamic themes with classic ASP or ASP.NET 1.x. I have done this before but master page definately makes life a lot easier.



03/13/2006 by caleb

hi, good day ppl!!


i am not using any master page but i would like to create some themes to my website. is it possible to do that? like passing the themes value through Session or etc? any idea or suggestion? by the way, i am still very new to programming and that is why i didnt use master page at the very first place.


please help!! thanks a lot in advance


 


regards,


caleb



02/25/2006 by manny
    Hello,
This might be off the subject but how do you set your ccs to be Mozilla Firefox friendly?  Everytime I render my site with Firefox, it is not render the same as IE 6.

thanks,
manny



Back to the top