Friday, April 27, 2012

Implementing the theme concept in C# client application

- Shanthi karthika
Its a common practice to include images either from the project resource files or from the settings file in any C# project. This heads to do changes in code for any change in an image. To overcome this and  to load the images at the runtime Theme Concept can be used.
The theme concept is a way of segregating the images to a class library and loading the images at the runtime. The images are to be changed only in the dll and so the source code will not be disturbed.
Below, I have created a demo project in which theme concept has been implemented. This sample can be used to know the way how theme concept can be used.

Sample Demo For Theme:
Following steps can be done to implement Theme.

Step 1:
In Visual Studio Create a windows application. For instance, here I name it is as CssStorage.

Step2:
Create an interface class inside the CssStorage and name it as InterfaceImages. Implement all the images in the interface which are needed for the application.
namespace CssStorage
{
public interface InterfaceImages
{
Bitmap AddButton { get; }
Bitmap DeleteButton { get; }
}

Compile CssStorage which will create a dll, for instance here it creates CssStorage.exe.

Step3:
Create a class library, for instance name it as CssTheme. Add a project resource file which contains the images that are needed for the application.

Step4:
Add the CssStorage.exe to CssTheme and make a reference to it.



Step 5:
Create a class in CssTheme for instance name it as Images, which implements the images for which interface have been build.

using CssStorage;

namespace CssTheme
{
 public class Images : InterfaceImages
 {
  public Bitmap AddButton
  {
   get { return Properties.Resource.AddButtonImage; }
  }
 public Bitmap DeleteButton
 {
  get { return Properties.Resource.DeleteButtonImage; }
 }
}
}


Step 6:
Compile CssTheme and extract the dll. Add the dll to the CssStorage. Now, in CssStorage make a call to the assembly to retrieve the path of CssTheme. Now call the images through the assembly.
Hashtable mAssemblies = new Hashtable();
Interface lCommand;
Assembly lAssembly = null;
String filename= “CssTheme”;

string themePath = Assembly.GetExecutingAssembly().Location.Replace(Assembly.GetExecutingAssembly().ManifestModule.ScopeName, "");
// Retrives the path where the CssTheme.dll Exists.

if (mAssemblies != null && mAssemblies.ContainsKey(fileName + ".dll") == false)
{
 lAssembly = Assembly.LoadFile(Path.Combine(themePath, fileName +     ".dll"));
 mAssemblies.Add(fileName + ".dll", lAssembly);
}

// retrived Images are casted to interface.
lCommand = default(InterfaceImages);
lCommand = (InterfaceImages)createObject(fileName + ".Images");

private object createObject(string lObjectType) //to retrive Images from the CssTheme
{
try
{
 object lObject = null; int lAssemblyCount = 0;
 lAssemblyCount = mAssemblies.Count;
 lAssembly = Assembly.GetCallingAssembly();
 lObject = lAssembly.CreateInstance(lObjectType);
 if (lObject == null)
 {
  lAssembly = Assembly.GetExecutingAssembly();
  lObject = lAssembly.CreateInstance(lObjectType);
 }
 if (lObject == null)
 {
  IDictionaryEnumerator enumerator = mAssemblies.GetEnumerator();
  while (enumerator.MoveNext())
  {
   lAssembly = (Assembly)enumerator.Value;
   lObject = lAssembly.CreateInstance(lObjectType);
   if (lObject != null)
   {
    break;
   }
  }
}
return lObject;
}
catch (DllNotFoundException ex)
{
throw ex;
}
catch (Exception ex)
{
throw ex;
}
}

Now the images will be retrieved and it can be used where ever needed by calling the Interface Object Icommand

uxAddPictureBox.Image = lCommand.AddButton;
uxDeletePictureBox.Image = lCommand.DeleteButton;

Step 7:
Compile the project. The images will be loaded at the runtime.

Implement the ThemeConcept and get new experience of loading images at runtime from a class library.