大雀软件园

首页 软件下载 安卓市场 苹果市场 电脑游戏 安卓游戏 文章资讯 驱动下载
技术开发 网页设计 图形图象 数据库 网络媒体 网络安全 站长CLUB 操作系统 媒体动画 安卓相关
当前位置: 首页 -> 技术开发 -> NET专区 -> Globalized Property Grid (一)

Globalized Property Grid (一)

时间: 2021-07-31 作者:daque

source code: globalizedpropertygrid_source.zip 48 kb.introduction

globalized property grid (一)图1

the property grid is a nice control to display properties and values. you create an instance of your class and assign it to the property grid. by using reflection a property grid extracts the properties of the class and displays its values. usually you meet some more requirements: it would be nice if there is a user friendly name displayed which may differ from the property member names used for the class. or the property name needs to be displayed in a different language. or if international software is required at all we need to display property names in more than one language. maybe with switching between the languages at runtime.so how to handle these requirements?fortunately there is a real good support for international software in .net integrated. even so it is possible to customize the displaying of the property names and descriptions. let us see how to apply this.globalization and localization

first, let's have a short look on developing international software with .net. it is a process that mainly takes two steps: globalization and localization.simply defined:globalization means the process of preparing your code to be able to support different languages. this is done by eliminating language or culture dependencies from your code to become culture-neutral. that is to avoid using hardcoded strings or message to be displayed to the user.localization means the process of separation of regional settings from the application code. instead provide them separately as resources..net has a bunch of classes integrated to support the development of international software. these classes are located in the namespaces system.globalization and system.ressources. cultureinfo is the class that holds information about a certain language, as formatting of numbers and dates, calendar to use, decimal character... . the current language is set by assigning an instance of cultureinfo to the property currentuiculture of the thread instance representing the current thread: thread.currentthread.currentuiculture = new cultureinfo("de");the example sets german as the current language. the languages identifiers are standard by iso 639-1.the application resources are requested by using an instance of resourcemanager. the resource manager uses the currently set cultureinfo object to access the correct local resources. resourcemanager rm = new resourcemanager("mystringtable",this.gettype().assembly);string message = rm.getstring ("mymessage");the example accesses the string named 'mymessage' from the stringtable named 'mystringtable'. we will use this support later on when we are localizing the property names to be displayed by the property grid. but before let us define a sample project for demonstration purpose.creating a sample project

globalized property grid (一)图2

for demonstration purpose select a windows application as a new project type. use the main form of type form1 as a host for a property grid control. select a property grid control from toolbox and drag it to the form.additionally define a test class that provides some properties to be displayed in the property grid. select "add class..." and add a c# class named person.cs to the project.the test class models a person and should look like this:// person is the test class defining three properties: first name, last name and age.public class person : globalizedobject{private string firstname = "";private string lastname = "";private int age = 0;public person() {}public string firstname{get { return firstname; }set { firstname = value; }}public string lastname{get { return lastname; }set { lastname = value; }}public int age{get { return age; }set { age = value; }}}now we are prepared for an initial version. initial version

globalized property grid (一)图3

an instance of person is created and assigned to the property grid in the form1_load event handler.private void form1_load(object sender, system.eventargs e){// instantiate test class and set some dataperson = new person();person.firstname = "max";person.lastname = "headroom";person.age = 42;// assign to property gridpropertygrid1.selectedobject = person;}after compiling the initial version displays the public properties of the person class in the property grid with property name and value. the displayed property name matches exactly the name of the property name of the class. the property 'lastname' is displayed as 'lastname'. that is fine for startup. now let us customize the displaying of property names.localizing property names

to customize how properties are displayed, person has to implement an interface called icustomtypedescriptor. icustomtypedescriptor allows an object to provide dynamic type information about itself. this interface is used to request a collection of property descriptor objects. one for each property. this matches our point of interest.a property descriptor object is of type propertydescriptor by default and provides information about a certain property, for example which name or desription text to display, what we are interested in. icustomtypedescriptor and propertydescriptor are located in the namespace system.componentmodelby default, there is the property name of the class returned as display name and an empty string as description.we override this behaviour by providing our own property descriptor. let us start with the implementation of icustomtypedescriptor. because it may common code for all customized business classes, so it is placed into a base class from which person can derive.the base class is called globalizedobject and can be found in descriptors.cs. /// /// globalizedobject implements icustomtypedescriptor./// the main task of this class is to instantiate our own specialized property descriptor./// public class globalizedobject : icustomtypedescriptor{...our implementation overrides getproperties() only and creates a collection of custom property descriptors of type globalizedpropertydescriptor and returns them to the caller instead of the default ones. public propertydescriptorcollection getproperties(){// only do onceif ( globalizedprops == null) {// get the collection of propertiespropertydescriptorcollection baseprops = typedescriptor.getproperties(this, true);globalizedprops = new propertydescriptorcollection(null);// for each property use a property descriptor of our own that is able to be globalizedforeach( propertydescriptor oprop in baseprops ){// create our custom property descriptor and add it to the collectionglobalizedprops.add(new globalizedpropertydescriptor(oprop));}}return globalizedprops;}the rest of the methods are delegating the call to the .net class typedescriptor providing static methods for default type information.the custom property descriptor class globalizedpropertydescriptor derives from propertydescriptor. the default property descriptor is passed as an argument in the constructor. we use this instance to provide default behavior for all methods we don't override. the class can be found in descriptor.cs, too. /// /// globalizedpropertydescriptor enhances the base class bay obtaining the display name for a property/// from the resource./// public class globalizedpropertydescriptor : propertydescriptor{private propertydescriptor basepropertydescriptor; private string localizedname = "";private string localizeddescription = "";public globalizedpropertydescriptor(propertydescriptor basepropertydescriptor) |: base(basepropertydescriptor){this.basepropertydescriptor = basepropertydescriptor;}...the focus of interest are the properties displayname and description. displayname will be overridden to return a string obtained from resources. public override string displayname{get {// build the resource string table name. this sample uses the class name prefixed by the namespace. string tablename = basepropertydescriptor.componenttype.namespace + "." + basepropertydescriptor.componenttype.name;// build the resource identifier. this sample uses the default property name string displayname = this.basepropertydescriptor.displayname;// now use resource table name and string id to access 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);// store the localized display name this.localizedname = (s!=null)? s : this.basepropertydescriptor.displayname; return this.localizedname;}}the implementation of displayname uses the class name as a resource string table name and the property name as the string identifier by default.the implementation of property description is nearly the same except that the resource string id is built by property name appended by 'description'.next step is to derive person from globalizedobject. public class person : globalizedobjectokay, having done this, our code is prepared to be globalized. now let us do localization. we define resources for supported languages and make them selectable. defining resources

our sample will support two languages, english and german. for each language and class we add an assembly resource file to our sample project. due to the fact that we use the class name as resource table name, we have to name the resource file same as the class: person.de.resx and person.en.resx. additional fact for this naming is visual studio will recognized these resource files and generate the appropriate resource dlls (.net calls them satelite assemblies. they contain no application code, only resource definitions).note: it is good to have a default language integrated into your application. in our case i have used german, so i name the german resource file person.resx instead of person.de.resx. in this case german language will be integrated into the application and no satelite assembly will be generated then. the default language resource is also used if a resource in the current language cannot be found, this is part of a process to find resources that ms calls 'fallback process'. the resource tables may look like this:

热门阅览

最新排行

Copyright © 2019-2021 大雀软件园(www.daque.cn) All Rights Reserved.