A quick read of most developer sites will reveal that WinForms is considered inferior to WPF. One of the most often cited reasons is the supposed difficulty in making application wide changes to the "look-and-feel" of an entire application.
In fact it is surprisingly easy to produce an application in WinForms that is easily configurable both at design-time and run-time, if you simply eschew the use of the standard controls and derive your own from them.
Take the TextBox as an example. It is hard to imagine a Windows application that does not call for the use of a TextBox at some stage or other. Therefore, having your own TextBox will always make sense. Take the following example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace StackOverflowDocumentation
{
public class SOTextBox : TextBox
{
public SOTextBox() : base()
{
base.BackColor = SOUserPreferences.BackColor;
base.ForeColor = SOUserPreferences.ForeColor;
}
protected override void OnEnter(EventArgs e)
{
base.BackColor = SOUserPreferences.FocusColor;
base.OnEnter(e);
}
protected override void OnLeave(EventArgs e)
{
base.BackColor = SOUserPreferences.BackColor;
base.OnLeave(e);
}
}
}
One of the things that users find most helpful in a data entry form, with many input boxes, is to have the background colour of the box with focus change. Visibly it is easier to see, than a standard blinking vertical cursor. The above code provides a TextBox that does precisely that.
In the process it makes use of the static properties of a static class. I give below an extract from mine:
using System;
using System.Threading;
using Microsoft.Win32;
using System.Globalization;
using System.Data;
using System.Drawing;
namespace StackOverflowDocumentation
{
public class SOUserPreferences
{
private static string language;
private static string logPath;
private static int formBackCol;
private static int formForeCol;
private static int backCol;
private static int foreCol;
private static int focusCol;
static SOUserPreferences()
{
try
{
RegistryKey HKCU = Registry.CurrentUser;
RegistryKey kSOPrefs = HKCU.OpenSubKey("SOPrefs");
if (kSOPrefs != null)
{
language = kSOPrefs.GetValue("Language", "EN").ToString();
logPath = kSOPrefs.GetValue("LogPath", "c:\\windows\\logs\\").ToString();
formForeCol = int.Parse(kSOPrefs.GetValue("FormForeColor", "-2147483630").ToString());
formBackCol = int.Parse(kSOPrefs.GetValue("FormBackColor", "-2147483633").ToString());
foreCol = int.Parse(kSOPrefs.GetValue("ForeColor", "-2147483640").ToString());
backCol = int.Parse(kSOPrefs.GetValue("BackColor", "-2147483643").ToString());
focusCol = int.Parse(kSOPrefs.GetValue("FocusColor", "-2147483643").ToString());
}
else
{
language = "EN";
logPath = "c:\\windows\\logs\\";
formForeCol = -2147483630;
formBackCol = -2147483633;
foreCol = -2147483640;
backCol = -2147483643;
focusCol = -2147483643;
}
}
catch (Exception ex)
{
//handle exception here;
}
}
public static string Language
{
get
{
return language;
}
set
{
language = value;
}
}
public static string LogPath
{
get
{
return logPath;
}
set
{
logPath = value;
}
}
public static Color FormBackColor
{
get
{
return ColorTranslator.FromOle(formBackCol);
}
set
{
formBackCol = ColorTranslator.ToOle(value);
}
}
public static Color FormForeColor
{
get
{
return ColorTranslator.FromOle(formForeCol);
}
set
{
formForeCol = ColorTranslator.ToOle(value);
}
}
public static Color BackColor
{
get
{
return ColorTranslator.FromOle(backCol);
}
set
{
backCol = ColorTranslator.ToOle(value);
}
}
public static Color ForeColor
{
get
{
return ColorTranslator.FromOle(foreCol);
}
set
{
foreCol = ColorTranslator.ToOle(value);
}
}
public static Color FocusColor
{
get
{
return ColorTranslator.FromOle(focusCol);
}
set
{
focusCol = ColorTranslator.ToOle(value);
}
}
}
}
This class uses the Windows registry to persist the properties, but you can use a database or a settings file if you prefer. The advantage of using a static class in this way is that application wide changes can be made not only at design-time, but also by the user at run-time. I always include a form in my applications allowing the user to change the preferred values. The save function not only saves to the Registry (or database etc), but it also at run-time changes the propeties in the static class. Note that static properties of a static class are not constant; in this sense they may be regarded as application wide variables. This means that any form opened subsequent to the changes being saved will immediately be affected by any changes saved.
You will easily be able to think of other application wide properties that you would like to be configurable in the same way. Fonts are another very good example.