.NET Forum / Windows Forms / Design Time / April 2005
How to build a Design Time PropertyGrid
|
|
Thread rating:  |
Frank Kwong - 26 Mar 2005 03:27 GMT My goal is to build a non-visual custom component with a PropertyGrid like the TableStyles property of the dataGrid as a Design Time data input tool. I got as far as the following –
System.Collections.ArrayList rsource = new System.Collections.ArrayList(); public ArrayList Source1 { get {return rsource;} set {rsource = value;} }
Instead of an ArrayList, Source1 is really –
public class Source { public string FirstName; public string LastName; public string Phone; }
When I compile this component and dropped it in the test winform and I got Source1 (collection) in the property. But when I click on (Collection), it gives me the Object Collection Editor. When I add a Member, I got System.Object. Now, if I somehow can define the System.Object Properties as FirstName, Lastname, Phone as the properties of rsource, and if I can retrieve these values for each members I added at runtime then the job is done.
There are a lot of PropertyGrid references in this forum and most of them are using the PropertyGrid in runtime instead of Design time. Can somebody point me to the right direction to get some sample codes to setup the System.Object.Properties at Design time.
Thanks,
Frankk
joeycalisay - 29 Mar 2005 03:22 GMT you should have a strongly-typed collection of Source objects. Then apply a DesignerSerializationVisibiltity.Content attribute to the Source1 property. You also need a TypeConverter to serialize your Source objects in the InitializeComponent section properly
 Signature Joey Calisay http://spaces.msn.com/members/joeycalisay/
> My goal is to build a non-visual custom component with a PropertyGrid like > the TableStyles property of the dataGrid as a Design Time data input tool. [quoted text clipped - 31 lines] > > Frankk frankk - 29 Mar 2005 05:18 GMT > you should have a strongly-typed collection of Source objects. Then apply a > DesignerSerializationVisibiltity.Content attribute to the Source1 property. > You also need a TypeConverter to serialize your Source objects in the > InitializeComponent section properly Joey, Any chance of seeing some sample code. All the examples in many forums only deal with run time propertygrid and I cannot find any reference doing it in design time (just like the TableStyle design time collection property of the dataGrid).
Thanks,
Frankk
joeycalisay - 29 Mar 2005 06:12 GMT get some ideas here: http://windowsforms.net/articles/shapedesigner.aspx http://www.divil.co.uk/net/articles/designers/collectioncontrols.asp
 Signature Joey Calisay http://spaces.msn.com/members/joeycalisay/
> > you should have a strongly-typed collection of Source objects. Then apply a > > DesignerSerializationVisibiltity.Content attribute to the Source1 property. [quoted text clipped - 10 lines] > > Frankk frankk - 29 Mar 2005 16:57 GMT > get some ideas here: > http://windowsforms.net/articles/shapedesigner.aspx > http://www.divil.co.uk/net/articles/designers/collectioncontrols.asp Joey,
I have these articles in my "collection". Do not see any hint in how to go by doing that (or it is betyond my reach). I am beginning to think this idea is impossible. Be able to store collection data in design time is so useful and it is hard to imagine that tons and tons of articles, tutorial code and forum discussion did not cover this aspect.
Thanks,
Frankk
mujdat - 02 Apr 2005 21:57 GMT Hi.. May be i misunderstood your problem. Propery grid renders Properties not Fields. You must convert fields of the class to properites.. public class Source { string _firstname ; [DefaultProperty] // use for the name of object resides on left list box
public string FirstName { get { _ firstname =""; } set { firstname = value; } } ............ .............
> My goal is to build a non-visual custom component with a PropertyGrid like > the TableStyles property of the dataGrid as a Design Time data input tool. [quoted text clipped - 32 lines] > > Frankk Frank Kwong - 03 Apr 2005 23:52 GMT OK.. this is good for a string property. Now how to build a collection property in "DesignTime" like the TableStyle property of the dataGrid? All tutorials and sample codes are done in RunTime and not DesignTime.
Frankk
Mujdat Dinc - 04 Apr 2005 10:21 GMT Hi, Here is sample form a component .. You must derive CollectionBase for yor object collection
public class MyOBject { string _name; public string Name { get { return _name; } set { _name = value; } } } public class MyObjectCollection:CollectionBase { public MyOBject this[ int index ] { get { return( (MyOBject) List[index] ); } set { List[index] = value; } }
public int Add( MyOBject value ) { return( List.Add( value ) ); }
public int IndexOf( MyOBject value ) { return( List.IndexOf( value ) ); }
public void Insert( int index, MyOBject value ) { List.Insert( index, value ); }
public void Remove( MyOBject value ) { List.Remove( value ); }
public bool Contains( MyOBject value ) { return( List.Contains( value ) ); } }
//In component MyObjectCollection _objects = new MyObjectCollection(); public MyObjectCollection Objects { get { return _objects; } set { _objects = value; } }
> OK.. this is good for a string property. Now how to build a collection > property in "DesignTime" like the TableStyle property of the dataGrid? All > tutorials and sample codes are done in RunTime and not DesignTime. > > Frankk frankk - 05 Apr 2005 04:14 GMT Mujdat,
This sample works like magic for me. Thanks. Now, if the values entered to the collection can be stored with the code. Then it would function the same as the TableSTyle property of dataGrid. In the TableStyle property, all the values entered are retained upon saving the .cs code file such that it is there when I reload the code. In your example, how can I make the _name values stay with the code.
Thanks,
Frankk
> Hi, > Here is sample form a component .. [quoted text clipped - 74 lines] >> >>Frankk Mujdat Dinc - 05 Apr 2005 08:56 GMT Hi. This time you must implement type converter to help serializer to render the code..
[TypeConverter(typeof(MyObjectConverter))] // Declare converter attirbute public class MyOBject { string _name; // This is for constructor with values public MyOBject(string name ) { _name = name; } // Default contructor for collection editor public MyOBject() { _name = ""; } public string Name { get { return _name; } set { _name = value; } } } public class MyObjectConverter:TypeConverter { public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { if(destinationType == typeof(System.ComponentModel.Design.Serialization.InstanceDescriptor)) return true; return base.CanConvertTo (context, destinationType); } public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { if(destinationType == typeof(System.ComponentModel.Design.Serialization.InstanceDescriptor)) { MyOBject val = (value as MyOBject); System.Reflection.ConstructorInfo ci = typeof( MyOBject).GetConstructor(new Type [] {typeof( string) }); if(ci !=null) return new System.ComponentModel.Design.Serialization.InstanceDescriptor(ci,new object[] {val.Name}); } return base.ConvertTo (context, culture, value, destinationType); } }
public class MyObjectCollection:CollectionBase { public MyOBject this[ int index ] { get { return( (MyOBject) List[index] ); } set { List[index] = value; } }
public int Add( MyOBject value ) { return( List.Add( value ) ); }
public int IndexOf( MyOBject value ) { return( List.IndexOf( value ) ); }
public void Insert( int index, MyOBject value ) { List.Insert( index, value ); }
public void Remove( MyOBject value ) { List.Remove( value ); }
public bool Contains( MyOBject value ) { return( List.Contains( value ) ); } }
MyObjectCollection _objects = new MyObjectCollection(); [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public MyObjectCollection Objects { get { return _objects; } set { _objects = value; } } ----- Original Message ----- From: "frankk" <frank@aspdb.com> Newsgroups: microsoft.public.dotnet.framework.windowsforms.designtime Sent: Tuesday, April 05, 2005 6:14 AM Subject: Re: How to build a Design Time PropertyGrid
> Mujdat, > [quoted text clipped - 88 lines] >>> >>>Frankk Frank Kwong - 05 Apr 2005 18:16 GMT Mujdat,
This code works great.
Thanks again,
Frankk
Frank Kwong - 06 Apr 2005 00:26 GMT Mujdat, Can you help explain the case that when data are entered into the collection at designtime let say 3 items - name_1, name_2 and name_3. Would accessing these data the same in Designtime and also at Runtime?
Thanks,
Frankk
Mujdat Dinc - 06 Apr 2005 08:58 GMT if you want to see it in designer just like other componets inherit your object from System.Component.Mode.Component then you can see your object in design time and code but this time these object appears in designetime surface...
> Mujdat, > Can you help explain the case that when data are entered into the [quoted text clipped - 5 lines] > > Frankk Frank Kwong - 06 Apr 2005 03:51 GMT Mujdat,
I have the following and how to modify the TypeConverter to retain both "Name" and "ID" instead of just the "Name". If I use all string types, would the converter works on all of them.
[TypeConverter(typeof(MyObjectConverter))] public class MyObject { string _name, _id; public MyObject(string name) { _name = name; } public MyObject() { _name = ""; } public string Name {get {return _name;} set{_name = value;}} public string ID {get {return _id;} set{_id = value;}} }
Thanks,
Frankk
Mujdat Dinc - 06 Apr 2005 08:55 GMT Hi.. Serializers user typeconvertors to gain InstanceDescriptor to to know howto serialize contructor. so you must implemet your constructor to form object like .. public MyObject(string name,int id ) { _name = name; _id = id;
} then you must modify type converter to return correct instancedescriptor..
System.Reflection.ConstructorInfo ci = typeof( MyOBject).GetConstructor(new Type [] {typeof( string) ,typeof(int)});
this find our new constructor.. and finnaly pass the values(name and id ) that will create the object to instance descirptor..
if(ci !=null) return new System.ComponentModel.Design.Serialization.InstanceDescriptor(ci,new object[] {val.Name,val,ID});
that s it...
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { if(destinationType == typeof(System.ComponentModel.Design.Serialization.InstanceDescriptor)) { MyOBject val = (value as MyOBject); System.Reflection.ConstructorInfo ci = typeof( MyOBject).GetConstructor(new Type [] {typeof( string),typeof(int) }); if(ci !=null) return new System.ComponentModel.Design.Serialization.InstanceDescriptor(ci,new object[] {val.Name,val.ID}); } return base.ConvertTo (context, culture, value, destinationType); }
> Mujdat, > [quoted text clipped - 20 lines] > > Frankk Frank Kwong - 06 Apr 2005 18:20 GMT Mujdat, Again, the code works great. My question is that I have a 50 x 50 data set and the most convenient way to store them is in the DesignTime Property grid. Takes a while to have a guru to provide a designtime solution. Is this a good practice? Is there any down side?
Frankk
Frank Kwong - 06 Apr 2005 23:34 GMT Another question -
How to implement an openfiledialog into a property in order to get a filename into the property?
Frankk
Mujdat Dinc - 07 Apr 2005 08:10 GMT Hi. Use EditorAttribute with standart FileNameEditor or implement your custom editor for filitering files(e g Txt files)
string _filename=""; [EditorAttribute(typeof(System.Windows.Forms.Design.FileNameEditor), typeof (System.Drawing.Design.UITypeEditor))] // [EditorAttribute(typeof(MyFileEditor), typeof //(System.Drawing.Design.UITypeEditor))] public string FileName { get { return _filename; } set { _filename = value; } }
public class MyFileEditor:UITypeEditor { public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { //IUIService us = provider.GetService(typeof(IUIService)) as IUIService; //if(us != null) { OpenFileDialog fd = new OpenFileDialog(); fd.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" ; fd.RestoreDirectory = true; if(fd.ShowDialog() == DialogResult.OK) { value = fd.FileName; } } return value; }
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; }
}
> Another question - > > How to implement an openfiledialog into a property in order to get a > filename into the property? > > Frankk FK - 09 Apr 2005 05:31 GMT Mujdat,
Again...works like a charm. My component is looking pretty good now.
I studied the MS tutorial and I try to setup the following string property -
[DescriptionAttribute("Use external data source"),DefaultValueAttribute("None"), CategoryAttribute("Project")]
public string ExternalData {get {return _externaldata;} set {_externaldata = value;}}
There is no error in compile, there is no help window at the bottom to show the "Description" and the Default value is not effective. I can set the default value in ->
string _externaldata = "None";
and it seems to work. But does these attributes applies to the non-visual component?
Thanks,
Frankk
Frank Kwong - 09 Apr 2005 06:02 GMT Mujdat,
In MyFileEditor:UITypeEditor ->
fd.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
seems to be not effective. Only All files (*.*) shows. Setting other properties like fd.InitialDirectory=xxxx is not effective etiher. What could be the reason?
Frankk
Mujdat Dinc - 11 Apr 2005 09:32 GMT Did you use the correct Attibute? my sample uses default one(default System.Windows.Forms.Design.FileNameEditor does not have filter ) you have to use second one [EditorAttribute(typeof(System.Windows.Forms.Design.FileNameEditor), typeof (System.Drawing.Design.UITypeEditor))] [EditorAttribute(typeof(MyFileEditor), typeof //(System.Drawing.Design.UITypeEditor))]
> Mujdat, > [quoted text clipped - 7 lines] > > Frankk Frank Kwong - 11 Apr 2005 15:57 GMT My fault, openfiledialog works now.
Also, the follwing provides a dropdown for On/Off. Is it possible to pass in the StandardValuesCollection values like {"True","False"} kind of like a generic dropdown Converter?
Frankk
public class ONOFFDropDownConverter: StringConverter { public override bool GetStandardValuesSupported(ITypeDescriptorContext context) {return true;} public override StandardValuesCollection GetStandardValues (ITypeDescriptorContext context) { return new StandardValuesCollection(new string[]{"On","Off"}); } }
Frank Kwong - 07 Apr 2005 03:25 GMT Seems like after the properties are defined at DesignTime it cannot be "cleared" via -> _objects.Clear(); at runtime. The _objects will clear (and can be filled with different values) at runtime but when application is restarted the "default" designtime values will stay. Is this observation correct?
Frankk
Mujdat Dinc - 07 Apr 2005 08:35 GMT Runtime and desigtime creates uses same components nothing diffirent. But in design time your changes are serialized to file that persit changes for runtime and when you re-open your designer..
> Seems like after the properties are defined at DesignTime it cannot be > "cleared" via -> _objects.Clear(); at runtime. The _objects will clear [quoted text clipped - 4 lines] > > Frankk
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|