Saturday, June 30, 2007

ASP.NET Themes and Right-to-Left Languages

ASP.net provides a great built-in support for managing localized resources, but when it comes to themes and managing a right-to-left user interface! there isn't much out of the box. And you have to implement your own logic to obtain a higher level of manageability as in the case of localized resources, therefore I'll follow an approach similar to .net localized resources handling.

I'll be using a single folder for .skin and .css files, I see no need to seperate them into two folders and assigning both Page.Theme and Page.StyleSheetTheme properties. also I'll create a base page class to be used across all pages.

Let's say we have a left-to-right theme named "Default" and we want to add a matching one for right-to-left languages, we'll do the following:

1. Add another one with same name but extend it with .rtl suffix ("Default.rtl"), this will be our matching right-to-left theme.

2. Now, we have two names for the same theme. To remove that burden and keep dealing with one name! we'll benefit from the property Page.Theme, this propery is virtual. therefore we are going to override it as follows:

public class BasePage:System.Web.UI.Page
{
public override string Theme
{
get {
if(Thread.CurrentThread.CurrentUICulture.TextInfo.IsRightToLeft)
return string.Format("{0}.rtl",base.Theme);
else
return base.Theme;
}
set
{
base.Theme = value;
}
}
}

So if the current thread UI language is right-to-left, the matching theme will be selected automatically. if you are using Page.StyleSheetTheme you can do the same:
public class BasePage:System.Web.UI.Page
{
public override string Theme
{
get
{
if(Thread.CurrentThread.CurrentUICulture.TextInfo.IsRightToLeft)
return string.Format("{0}.rtl",base.Theme);
else
return base.Theme;
}
set
{
base.Theme = value;
}
}
}

You'll face some cases where you use horizontal alignment directly inside your aspx pages or code behind, for example if you set the alignment right for one of your controls and view the page in right-to-left mode; you'll notice that you want it to be left. To help resolve such issue you can add some other helpfull properties to our base page:

The following properties will help in auto set the correct alignment in a flow-layout pages, where right means left and left means right.

public HorizontalAlign Right
{
get
{ if(Thread.CurrentThread.CurrentUICulture.TextInfo.IsRightToLeft)
return HorizontalAlign.Left;
else
return HorizontalAlign.Right;
}
}

public HorizontalAlign Left
{
get
{
if(Thread.CurrentThread.CurrentUICulture.TextInfo.IsRightToLeft)
return HorizontalAlign.Right;
else
return HorizontalAlign.Left;
}
}

One last tip before I finish this writing, in cases you have common .css files or images there is no need to make duplicates; simply reference the style using @import directive: @import url("../default/common.css") and the same relative referencing applies for images.