Windows Forms Designer

The Windows Forms Designer has a localization feature built in to it. From each form you can turn on localization from the forms properties and all localizable properties are written to an Xml resource file (one for each form) that gets embedded into the assembly once compiled. The resulting generated code then manages the creation of a resource manager instance and the fetching of those resources to populate the localizable property values.

In .NET 2.0 the resource manager used is based on the ComponentResourceManager that inherits from System.Resources.ResourceManager. The key feature that the ComponentResourceManager adds is the ApplyResources() method that will go off and find all the resources for a component and use Reflection to apply the resource values to properties of that component. Unfortunately it only implements the constructor that takes a single type parameter and thus can only be used with assembly embedded resources once again. In order to implement the other constructors for System.Resources.ResourceManager the ComponentResourceManager had to be completely rewritten rather than inherited. The Windows Forms designer localization feature is tightly coupled to the ComponentResourceManager and most of the code dom provider model is inaccessible and rarely uses interfaces, thus it is not possible to extend the feature to work with the Resource Application Block. All is not lost, however, so please read on.

The CodeDomProvider Model

The code dom provider model is responsible for the automatic generation of source code to render a form design. A key feature is that a single model works for any supported .NET language so you can code a source generator without having to worry about which language is to be used. A set of code serializers exist to emit code for various aspects of a managed program, so one exists for fields, another for properties and others for methods, namespace, class etc. In addition to that there is a CodeDomLocalizationProvider that manages resource allocation to property values.

Underpinning all serializers is the CodeDomSerializerBase abstract class and yes, you guessed it, that is where the primary resource oriented methods reside like SerializeResource() and SerializeToResourceExpression() that both use the ResourceCodeDomSerializer responsible for serializing resources to and from a resource store using a SerializationResourceManager derived from a ComponentResourceManager. These are all internal or private classes.

The ExtendedComponentResourceManager

The ExtendedComponentResourceManager was written to implement all of the System.Resource.ResourceManager constructors and to provide the ApplyResources() method found in the ComponentResourceManager. The ExtendedComponentResourceManager was then used as the base class for all resource managers in the Resource Application Block. Unfortunately, because it was not possible to inherit from the ComponentResourceManager this cannot be used with the existing CodeDomProvider model.

Using the Resource Application Block with Windows Forms

The Resource Application Block can still be used effectively with Windows Forms without too much additional effort. To do this you switch off the built-in localization feature (localization is off by default) and apply your resources to localizable component properties in your form class constructor using a Resource Application Block resource manager ApplyResources() method.

Getting Windows Form Component Properties into Resource Storage

To do this we cheat a little bit. If you temporarily switch on the built-in localizable feature for each form by setting the Localizable form property to true the Windows Forms Designer will create an xml resource file (.resx) attached to the form. You can then transfer the resource items in these xml files to the resource store (or stores) of your choice. Switch off the localization feature and configure a resource manager (or managers) in your application configuration file to manage your chosen resource store (or stores).

Applying Resources to Windows Form Component Properties

With the built-in localization feature switched off, default values will initially be applied to localizable component properties in the generated code, these values will be replaced when you run the ApplyResources() method in the forms constructor. Create a Resource Application Block resource manager in the normal fashion and then use the ApplyMethod() for each component represented on the form in turn, not forgetting the form itself. The following code sample will demonstrate this technique:

[C#]
// Our resource manager has an instance name of "Form Resource Manager" in this example
// The resource store holds a set of resources with keys prefixed with the component name, or "$this" for the form itself
// for example, for the comboDays component you will use a prefix of "comboDays" in the ApplyResources() method 
// where the key name of the Text property in the resource store will be "comboDays.Text"
public MessageOfTheDayForm ()
{
    // auto-generated method to initialise all form components
    InitializeComponent();
    // apply resources, you must do this after you have initialised all the form components
    ResourceManager formResources = ResourceFactory.GetResourceManager("Form Resource Manager");

    this.SuspendLayout();
    // for each component give the ApplyResources() method the component object itself and the resource key prefix string
    formResources.ApplyResources(this, "$this");
    formResources.ApplyResources(this.comboCulture, "comboCulture");
    formResources.ApplyResources(this.comboDays, "comboDays");
    formResources.ApplyResources(this.labelMessageOfTheDay, "labelMessageOfTheDay");
    formResources.ApplyResources(this.pictureFlag, "pictureFlag");
    formResources.ApplyResources(this.textMessage, "textMessage");
    this.ResumeLayout(false);
}


The form in the example looks like this:
Message of the Day Form

For the full working sample see the windows application in The QuickStart Sample Applications

Last edited Dec 17, 2009 at 1:15 PM by ewdev, version 2

Comments

No comments yet.