Globalized Property Grid (二)
发表于:2007-06-30来源:作者:点击数:
标签:
There are two entries for each property, name and description. Now that we have different sets of resources and globalized code that is able to extract strings to be displayed depending on the current language. Our code should be updated to
There are two entries for each property, name and description.
Now that we have different sets of resources and globalized code that is able to extract strings to be displayed depending on the current language. Our code should be updated to allow switching between supported languages.
Switching of current language
The only thing left is to make the two languages selectable. First we construct an array of supported languages in the constructor of the main form. We use the ISO 639-1 standard format for identifying languages as used by .NET: en for english, and de for german should be enough for this sample. Also, an instance of Person is created here. public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); supportedLanguages = new string[2]; supportedLanguages[0] = "en"; supportedLanguages[1] = "de"; // Instantiate test class and set some data person = new Person(); person.FirstName = "Max"; person.LastName = "Headroom"; person.Age = 42; }Second, we add a combobox named cbLang to the main form. This combo box is filled with the displayable language names. The displayable language names are obtained by using a CultureInfo object. Moreover the Person object is assigned to the property grid. We use the form load event handler for this. private void Form1_Load(object sender, System.EventArgs e) { // Setup combo box with languages available cbLang.Items.Insert(0,(new CultureInfo(supportedLanguages[0])).DisplayName); cbLang.Items.Insert(1,(new CultureInfo(supportedLanguages[1])).DisplayName); // Preselect the first one cbLang.SelectedIndex = 0; // Assign person to property grid PropertyGrid1.SelectedObject = person; }Last but not least, we define an event handler to be notified when the selected index changes in the combo box because we want to change the current language. We inform the current thread about the new current language by setting its static property CurrentUIThread to a new instance of CultureInfo initialized with the ISO 639-1 name. After setting the new language a refresh of the property grid is necessary. private void cbLang_SelectedIndexChanged(object sender, System.EventArgs e) { // get the language selected from combo box int lang = cbLang.SelectedIndex; if( lang == -1 ) return; // Set selected language as the current one Thread.CurrentThread.CurrentUICulture = new CultureInfo(supportedLanguages[lang]); // Refresh displayed properties PropertyGrid1.Refresh(); }That is a basic version that demonstrates how to display custom property names and descriptions. In the sample code there is one enhancement provided.
Enhancement
The default selection of the resource string is by the class name as string table name and the property name as the string definition. This can be superposed by using a .NET attribute.
The attribute GlobalizedPropertyAttribute is defined in Attributes.cs and can be applied as follows. [GlobalizedProperty("Surname",Description="ADescription", Table="GlobalizedPropertyGrid.MyStringTable")] public string LastName { get { return lastName; } set { lastName = value; } }The example defines the display name for the property name LastName can be found in stringtable GlobalizedPropertyGrid.MyStringTable and the string is identified by Surname, the optional description text is identified by ADescription.
To get this enhancement working an addition has to be made to the DisplayName and Description properties of the descriptor class GlobalizedPropertyDescriptor:
public override string DisplayName
{
get
{
// First lookup the property if GlobalizedPropertyAttribute instances are available.
// If yes, then try to get resource table name and display name id from that attribute.
string tableName = "";
string displayName = "";
foreach( Attribute oAttrib in this.basePropertyDescriptor.Attributes )
{
if( oAttrib.GetType().Equals(typeof(GlobalizedPropertyAttribute)) )
{
displayName = ((GlobalizedPropertyAttribute)oAttrib).Name;
tableName = ((GlobalizedPropertyAttribute)oAttrib).Table;
}
}
// If no resource table specified by attribute, then build it itself by using namespace and class name.
if( tableName.Length == 0 )
tableName = basePropertyDescriptor.ComponentType.Namespace + "." + basePropertyDescriptor.ComponentType.Name;
// If no display name id is specified by attribute, then construct it by using default display name (usually the property name)
if( displayName.Length == 0 )
displayName = this.basePropertyDescriptor.DisplayName;
// Now use table name and display name id to a
clearcase/" target="_blank" >ccess the resources.
ResourceManager rm = new ResourceManager(tableName,basePropertyDescriptor.ComponentType.Assembly);
// Get the string from the resources.
// If this fails, then use default display name (usually the property name)
string s = rm.GetString(displayName);
this.localizedName = (s!=null)? s : this.basePropertyDescriptor.DisplayName;
return this.localizedName;
}
}
This enhancement is commented out in the sample project. Remove the comment and recompile to see it working.
Summary
These are the steps to localize the names and descriptions displayed in the property grid:
- Implement the ICustomTypeDescriptor interface for your class to customize the display names and descriptions for properties.
- Override the GetProperties() method to return a collection of customized property descriptor classes.
- Override DisplayName and Description properties in the customized property descriptor class.
- The overriden versions should use a resource manager object to retrieve the display strings for the current language from the resource modules.
References
- Here you get a introduction to .
- A starting point for the component model and its customizing capabilities is to explore the .
Contributes
This code is inspired by a fellow (unfortunately I haven@#t found his name anymore) who showed how to provide user friendly names using vb code. I have adopted his work, using c# instead and prepared the code to be international and meet some recurrent real world requirements.
About the Author Gerd() works as senior consultant and lead architect with in Germany. He has deep technical experience in both Microsoft-Technologies ( OLE/COM/ActiveX (since 1994), C++(since 1990), MFC (since 1992) and .NET (since 2000) ) and the
Java-Platform (since 1997). His thematic main focus are component oriented architectures, distributed and web-based systems.
原文转自:http://www.ltesting.net