Http://blog.163.com/prince.king_521/blog/static/10689120420101019963625/
Introduction
When Designing User Controls (either winform or webform), for general simple attributes (string, Int, bool ...... The system automatically provides the corresponding type conversion. For example, we define an age attribute in the user control,
public int Age { get; set; }
Open the designer and you will see
This attribute is now available. We can set an int value for it. However, when we try to enter a string character, the system will pop up a "invalid attribute" window. In this process, we can see that the system has converted the type of age, this conversion fails because the type does not match.
Now let's write another complex property person. First, create a person class, which contains the name and age attributes:
public class Person { private string strName; private int intAge; public string StrName { get { return strName; } set { strName = value; } } public int IntAge { get { return intAge; } set { intAge = value; } } }
Then, in the user control, we create a property of person:
private Person person; public Person Person { get { return person; } set { person = value; } }
After opening the designer form, we can see that the person attribute is gray.
Why? The answer is simple. The system does not know how to display this attribute. But something must be displayed, right? The type Name of the person class is displayed. This is far from the location style we expected.
What is the difference? Type converter! When "zhangsan, 21" is entered in person, the type converter can automatically map these two attribute values to strname and intage. This is the role of the type converter. Next we will implement a person type converter.
Implementation type converter
First, create a new personconverter class to provide the ability to convert the person type. All comments are written in the code. You can see at a glance:
Public class personconverter: typeconverter {// indicates whether the content we set can be converted. // because we enter the string format of "zhangsan, 12, therefore, the string type conversion public override bool canconvertfrom (itypedescriptorcontext context, type sourcetype) {return sourcetype = typeof (string) | base. canconvertfrom (context, sourcetype);} // This method indicates the form in which the last complex attribute is represented. // If destinationtype = typeof (string), the last person is displayed in the form of "zhangsan, 21" // If destinationtype = typeof (instancedescriptor, person is displayed as the "windowsformscontrollibrary1.person" class name. Public override bool canconvertion (itypedescriptorcontext context, type destinationtype) {If (destinationtype = typeof (string) {return true;} If (destinationtype = typeof (instancedescriptor )) {return true;} return base. canconvertion (context, destinationtype);} // This method converts the input string to the person type public override object convertfrom (itypedescriptorcontext context, system. globalization. cultureinfo Culture, object Value) {If (value is string) {string [] V = (string) value ). split (','); If (v. getlength (0 )! = 2) {Throw new argumentexception ("invalid parameter format");} person CSF = new person {name = convert. tostring (V [0]), age = convert. toint32 (V [1])}; return CSF;} return base. convertfrom (context, culture, value) ;}// this is the method for displaying the property "person". Public override object Convertor (itypedescriptorcontext context, system. globalization. cultureinfo culture, object value, type destinationtype) {If (des Tinationtype = typeof (string) {person scope = (person) value; string result = scope. name. tostring () + "," + scope. age. tostring (); return result;} If (destinationtype = typeof (instancedescriptor) {constructorinfo CI = typeof (person ). getconstructor (New Type [] {typeof (string), typeof (int32)}); person scope = (person) value; return New instancedescriptor (CI, new object [] {scope. name, scope. age });} Return base. convertize (context, culture, value, destinationtype);} // The following two methods provide the ability to set sub-attributes separately. Public override bool getpropertiessupported (itypedescriptorcontext context) {return true;} public override propertydescriptorcollection getproperties (itypedescriptorcontext context, object value, attribute [] attributes) {return typedescriptor. getproperties (typeof (person), attributes );}}
Add the following sentence to the person attribute of the user control to specify the person converter:
[TypeConverter(typeof(PersonConverter))] public Person Person { get; set; }
Now let's take a look at the person design, which is the same as what we need.
Here we will teach you a way to be lazy, that is, when implementing the converter, you do not have to rewrite the top four methods, directly rewrite the two methods of "providing the ability to set sub-attributes separately. However, the "person" attribute displays the following results:
That is, the content displayed by person is changed, and the sub-attribute is set. It is enough for attributes with low requirements.
Implement the modal Attribute Editor
Previously, we implemented support for attribute settings when designing the location attribute, but sometimes we may not just need such complex attribute settings. For example, when setting the backgroundimage attribute, the system will pop up an interface for us to select an image:
Using this method will undoubtedly increase the convenience of selecting images. How can we implement this configuration?
First, create a new form, which will be displayed to users in the future (for example, the "select resource" form ). Let's take the person class as an example:
The background code of this form is as follows:
Private person _ person; Public personwindow (person) {initializecomponent (); person = person; textbox1.text = person. strname; textbox2.text = person. intage. tostring () ;}public person {get {return _ person ;}set {_ person = value ;}} /// <summary> /// confirm button /// </Summary> /// <Param name = "sender"> </param> /// <Param name = "E"> </param> private void button#click (Object sender, eventargs e) {person. strname = textbox1.text; person. intage = int. parse (textbox2.text );}
Note that the dialogresult of the confirm button must be set to dialogresult. OK, and the dialogresult OF THE cancel button must be set to dialogresult. Cancel. As for why we want to do this, you will know later.
Then we create a class personmodaleditor: system. Drawing. Design. uitypeeditor class. The Code is as follows:
Public override system. drawing. design. uitypeeditoreditstyle geteditstyle (system. componentmodel. itypedescriptorcontext context) {// indicates the form in which to open and edit the form return uitypeeditoreditstyle. modal;} // attribute editing method. This method is executed when you click the attribute button in the Properties window. Public override object editvalue (system. componentmodel. itypedescriptorcontext context, iserviceprovider provider, object Value) {// gets the service object. This object provides some functions for the winform editor iwindowsformseditorservice = (iwindowsformseditorservice) Provider. getservice (typeof (iwindowsformseditorservice); If (service = NULL) {return NULL;} person P = new person (); categorywindow form = new categorywindow (P ); // here we know it is Why do you want to set the dialogresult attribute of the confirm button. If (service. showdialog (form) = system. windows. forms. dialogresult. OK) {return P;} return value; // The system fills in the person Attribute Based on the returned value}
Finally, we add this sentence to the person property of the user control:
[Editor(typeof( PersonModalEditor), typeof(UITypeEditor))] public Person Person { get { return person; } set { person = value; } }
This statement specifies how the system opens the property editor of person. Let's take a look:
Author:
Qian lifeng
Source: http://qianlifeng.cnblogs.com
The copyright of this article is shared by the author and the blog. You are welcome to repost this article, but you must retain this statement without the author's consent. Otherwise, you will be entitled to pursue legal liability.