views:

104

answers:

6

Hello SO

My application has a set of base classes derived from almost all the UI controls XCombobox,XButton,XMenu etc. All these classes have some additional functionality apart from standard functionality (ex: Serialization capability)

I use all these controls in my test windows application.

I want to implement a concept similar to themes in my application.

Ex: Say if i need a blue background

I have a public property exposed in all controls which sets my controls (i.e XButton and XMenu) backcolor to blue

I feel this approach is lame. Tomorrow if my manager wants some other styling. I will have to go to every control and change the backcolor one by one ...not that i mind ;)....but this never makes me a good programmer.

Time for some application of a design pattern (strategy pattern shall i say ?)

Is there a possibility wherein i can just change in one central place and the property shall get applied to all of my UI controls ?

If yes... Please help me in realising the same. If not ... Suggestions for some more better ideas are welcome.

+1  A: 

You answered your question already.

Define constants for styling in central properties, and use these styling constants in your UI components :).

YoK
+2  A: 

Define a class that has properties for the colors (you can also add in properties for logos etc).

Then either have your constants in the code of that class, or read them in from some XML.

SteveCav
A: 

From what you're saying, it seems like if you just want to change the color, the easiest thing would just be to save the color in a variable somewhere, or have some kind of initialization function that every component calls where you can specify shared things like the color.
Also, since you mentioned that you're adding additional functionality to components, you may want to use a Decorator design pattern for that purpose.

muddybruin
+1  A: 

I would use a dependency injection container such as Unity for this, it will allow you to register you theme in a single location and have all of your controls resolve the theme whenever they need it.

For example, implement a simple interface which has the properties of the theme that each control will use.

interface IXTheme {
    Color BackColor { get; }
}

Wherever your control needs to fetch this, such as in OnPaintBackground, you make a simple call to fetch the color, using the CommonServiceLocator (This comes packaged with Unity already.)

protected override void OnPaintBackground(PaintEventArgs pevent)
{
    Color backColor = ServiceLocator.Current.GetInstance<IXTheme>().BackColor;
    ///...
}

Now, you can create you theme somewhere else based on that interface.

class XBlueTheme : IXTheme {
     Color IXTheme.BackColor { get { return Color.Blue; } }
}

You then register the theme with the container and use the container to resolve your form.

IUnityContainer container = new UnityContainer()
    .RegisterType<IXTheme, XBlueTheme>();
IServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => locator);

XForm myForm = container.Resolve<XForm>();
Mark H
A: 

You can make something like .skin file provided in .net web projects. Or just an xml file will do; For instance,

  1. Make a .skin file and add your controls and styling definitions there.
  2. Add the .skin file path in some public property of your control's base class.
  3. Add an event OnDraw, the all the controls override and color itself with the color defined in .skin.

Better try utilizing the existing .skin file; though I am not sure how would you plan to parse the .skin file.

<TextBox BackColor="Red" ForeColor="Blue"/>
<Button BackColor="White" ForeColor="Green"/>
<DropDownList BackColor="Cyan" ForeColor="Pink"/>

You can even extend the skin file by adding the cssClass property; and add styling according to css class defined in the css file.

<TextBox cssClass="TextLoginField"/>
<DropDownList cssClass="ComboLongList" />

Just thinking out loud! Btw, this article might give you an insight.

KMan
A: 

I guess the strategy pattern that you've mention fits the best. That book Head Fisrt Design patterns describes this issue very well. you need an interface say IStyle defined as a member of your base class so that the style behavior will be independent of your control inheritance.

Arseny