473,473 Members | 1,972 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

PropertyDescriptor

Hi,
Ive written a custom PropertyDescriptor wich lets me edit my
custom data items in the property editor,
however I now wish to expand it so that it can be used
to edit nested collections of such data items with the collection
editor that comes with the property editor.
[TypeConverter(typeof(ExpandableObjectConverter))]
public class MyClassDescriptor : PropertyDescriptor, ICustomTypeDescriptor
{
object Object;
getvalue,setvalue,propertycollection etc ...
}

propertyGrid.SelectedObject = new MyClassDescriptor (obj);

It was a while ago I wrote this, and taken me a while
to figure out how it worked again lol
but I cant seem to make any progress
on expanding it to collections.
I dont realy want to convert the collections of <myclassto collections of
<MyClassDescriptorwich is the only way ive thought of so far.

most of the data I need to edit is in the form of struct data fields or
contained in a dictionary of custom field names,objects

many thanks
Colin =^.^=
Jun 27 '08 #1
11 7289
OK, I'm a little confused with the setup; normally a type uses
ICustomTypeDescriptor to provide dynamic property support etc (for
things like data-binding); and a type or property is marked with
[TypeConverter] to customise conversion (string serialization etc) and
PropertyGrid behavior. It is unusual to see a PropertyDescriptor
*itself* marked with [TypeConverter].

I would expect you to still get collection support automatically -
like how the list editors generally work. However, if you want to
change the metadata of existing types, you can still do it - by using
things like TypeDescriptionProvider. However, this is not trivial nor
easy to summarise in a short post.

So; can you give a bit more detail on what you want this to do?

Marc
Jun 27 '08 #2
"Marc Gravell" <ma**********@gmail.comwrote in message
news:22**********************************@34g2000h sh.googlegroups.com...
OK, I'm a little confused with the setup; normally a type uses
ICustomTypeDescriptor to provide dynamic property support etc (for
things like data-binding); and a type or property is marked with
[TypeConverter] to customise conversion (string serialization etc) and
PropertyGrid behavior. It is unusual to see a PropertyDescriptor
*itself* marked with [TypeConverter].

I would expect you to still get collection support automatically -
like how the list editors generally work. However, if you want to
change the metadata of existing types, you can still do it - by using
things like TypeDescriptionProvider. However, this is not trivial nor
easy to summarise in a short post.

So; can you give a bit more detail on what you want this to do?

Marc
thanks it was a while since I wrote it,
I think you replied to my posts askign about it at the time,
however basically I dont have the ability to modify or add
a typedescriptor to the elements of the collections.

Im using what you described as a facade, and it seemed to avoid the need for
duplicate code
by combining the TypeConverter with the PropertyDescriptor.

I have a class wich is read from a file in a complicated fashion,
with some custom fields wich are also defined in the file,
these are handled by having a field dictionary.
the field types may also be types defined in the file.

my property descriptor nicely handles these fields,
and also some simple data fields
but for the collections the property editor
displays the contents of the collection,
but is unable to further expand them.

as an example one struct might have a custom field wich
equates to an array of struct Vector (ie 3 floats x,y,z)

my property editor can edit the values of the Vector but
only if it is a field or sub field of the object but
not if its in a collection.

I might look at TypeDescriptionProvider, hope it may be that it can do
all the work even if it is a bit more complicated.

unfortunatly a lot of the propertybag classes ive looked at seem quite
complicated and
I need to modify quite a lot to add my custom field stuff.
its hard to see what part of it is involved in the collection
editing.

many thanks
Colin =^.^=
Jun 27 '08 #3
Hi,
wel ive managed to get the collection editor to work
so that it picks up my CustomTypeDescriptor from the
DescriptorProvidor supplied to TypeDescriptor.AddProvider.

Ive also managed to solve my problem I had before
with nested struct fields without having to do copy back,
using TypedReference, and FeildInfo.SetValueDirect.

so the list gets updated correctly whith the pop up
collection editor fine, but when the list is displayed with
my TypeCOnverter wich is like the expandableObjectConverter,
it doesnt seem to use the same code as the pop up collection
editor as the array does not get updated.

I dont seem to be able to find where I can pick up
the index into the array to copy the data back to.
I wish to update the values directly rather than updating
a copy then copying the copy back.

thanks
Colin =^.^=


"Marc Gravell" <ma**********@gmail.comwrote in message
news:22**********************************@34g2000h sh.googlegroups.com...
OK, I'm a little confused with the setup; normally a type uses
ICustomTypeDescriptor to provide dynamic property support etc (for
things like data-binding); and a type or property is marked with
[TypeConverter] to customise conversion (string serialization etc) and
PropertyGrid behavior. It is unusual to see a PropertyDescriptor
*itself* marked with [TypeConverter].

I would expect you to still get collection support automatically -
like how the list editors generally work. However, if you want to
change the metadata of existing types, you can still do it - by using
things like TypeDescriptionProvider. However, this is not trivial nor
easy to summarise in a short post.

So; can you give a bit more detail on what you want this to do?

Marc

Jun 27 '08 #4
Re editing items in the property editor, the main tools here are
TypeConverter and UITypeEditor - you usually don't need custom
PropertyDescriptor provision.

Again - the setup is foreign, an unfortunately the devil is in the
detail with these things. Is there a way we can sketch this out with
very simple code?

As a starter for 10; is the setup anything like:

[TypeConverter(typeof(ExpandableObjectConverter))]
class Foo {
public string Name {get;set;}
}

[TypeConverter(typeof(ExpandableObjectConverter))]
class Bar {
private readonly List<Foofoos = new List<Foo>();

public List<FooFoos {get {return foos;}}
public DateTime DateOfBirth {get;set;}
}

And then what? What is the core thing we are trying to do? What do we
want to behave differently to just throwing that (Bar) at a
PropertyGrid?

[even if you can just talk me through it, it would really help me give
a sensible answer]

Marc
Jun 27 '08 #5
Re nested struct fields, that is usually sovled using
GetCreateInstanceSupported and CreateInstance on a custom
TypeConverter, and assumes that the parent property is writeable:

[TypeConverter(typeof(TupleConverter))]
struct Tuple
{
private readonly string val1, val2;
public string Val1 { get { return val1; } }
public string Val2 { get { return val2; } }
public Tuple(string val1, string val2)
{
this.val1 = val1 ?? "";
this.val2 = val2 ?? "";
}
public override string ToString()
{
return Val1 + "/" + Val2;
}
// and GetHashCode / Equals etc
}

class TupleConverter : ExpandableObjectConverter
{
public override bool
GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return true;
}
public override object CreateInstance(ITypeDescriptorContext
context,
System.Collections.IDictionary propertyValues)
{
return new Tuple((string) propertyValues["Val1"],
(string)propertyValues["Val2"]);
}
}

Marc
Jun 27 '08 #6
ah yes the devil is indeed in the detail well
yes unfortunatly its so complicated that its
hard to simplify easily,
and I need it to cope with any posible combination of devils.

the main diferences are that :-

most of the stuff I need to edit is custom data fields
that are implemented via a dictionary<fieldname,dataContainer>
this is actualy working ok, the data container describes the data and
includes
the data and links to next fields and lists of subfields etc.
it may include all maner of custom data structures

I simply use a facade wich can handle anything via reflection even
structures
in libraries. you helped me get this far before thanks.

However the problem comes when those structures I dont have access to
are in collections. I now seem to be able to solve this using the
AddProvider.

struct surface
{
Directx.Vector3 Origin,Normal,...
}

class/struct Poly
{
Surface surface; //texture offset etc.
Directx.Vector3[] Vectors;
}

class Polys
{
Directx.Vector3 Base;
EPolyFlags PolyFlags;
Poly[] Polygons;
}

class Model
{
Polys[] PolyList;
}

this is drasticaly simplified, theres maybe some 100k name tokens
involved in all, obviously not all is a data field description.

both poly and polys are semi custom defined,
and I think the create instance would be far to complicated to implement
to cope with all situations, and I dont expose all the data fields via
properties.

however the pop up colection editor copes fine at least with
the Vector array, I assume this is doing its own create instance?
it alows me to re size an array of structs,
so i assume its resizing the array, and copying the items
and then writing the new aray back to the parent.

I could do this myself, I have found the instance which is the actuall
collection,
or array, but I dont seem to have an indictaion of what the index is.

some things are obviously too dangerous to edit,
and Im happy as long as I can let the user edit certain things
like the Vertexes and the various flags. but wich just hapen to be in an
array of library structs.

Its just irking me that the pop up editor works ok for the vertexes,
but not when they are expanded in the property editor itself.

the application is a game editor, the game is unreal,
there are many diferent versions, and the game uses its own script.
some of the above structs are defined in the file,
I have to implement some of the structs in c# as there
are so many vertexes for instance it would be too slow otherwise,
particularly the ones above.

some of the things I need to alow the user
to do in the property editor are fine tune some vertexes etc.
problems come when models are made wich are snaped to a grid, then
rotated etc, and dont quite meet up and this cuases holes wich can
cuase players to fall out of the world.

obviously the more involved graphical editing is done with something better
than property grid.

although I could and do use my own struct for Vector,
at some stage this is pased to directx or some other graphics library,
and the property editor picks up whatever object is beneath the mouse
on the 3d view, wich inevitably involves some directx structs
for wich I cant edit the code obviously.

My main problem is I get so lost looking through all the
classes involved and trying to work out what does what where and when.
il look up UITypeEditor you mentioned.

some of the samples I find it so hard to find the parts
that are involved in the functionality I want to do.
plus ofc im heavily involved in the graphics wich
seems hard to find solutions for some of the simplest of things,
and converting the game file format, hopefully
I can make progrees on some actual usefull
editing features soon.

many thanks
Colin =^.^=

"Marc Gravell" <ma**********@gmail.comwrote in message
news:f7**********************************@f36g2000 hsa.googlegroups.com...
Re editing items in the property editor, the main tools here are
TypeConverter and UITypeEditor - you usually don't need custom
PropertyDescriptor provision.

Again - the setup is foreign, an unfortunately the devil is in the
detail with these things. Is there a way we can sketch this out with
very simple code?

As a starter for 10; is the setup anything like:

[TypeConverter(typeof(ExpandableObjectConverter))]
class Foo {
public string Name {get;set;}
}

[TypeConverter(typeof(ExpandableObjectConverter))]
class Bar {
private readonly List<Foofoos = new List<Foo>();

public List<FooFoos {get {return foos;}}
public DateTime DateOfBirth {get;set;}
}

And then what? What is the core thing we are trying to do? What do we
want to behave differently to just throwing that (Bar) at a
PropertyGrid?

[even if you can just talk me through it, it would really help me give
a sensible answer]

Marc

Jun 27 '08 #7
It is indeed the UITypeEditor that provides the elipsis [...] and the
popup collection editor; but there are actually several inbuilt
collection editors that just look the same - for example, you mention
arrays - ArrayEditor is a subclass of CollectionEditor with array-
specific load/save code.

You could provide your own CollectionEditor implementation?

Re the large structs - you mention speed; is this from benchmarking?
Because from a speed perspective, large structs are actually a bad
thing, since they clog up the stack and have to be blitted constantly.
It also makes it very hard to sensibly make changes (mutable structs =
bad). Classes would have a slightly bigger footprint overall
(references + object headers + data, instead of just data), but with
classes you only need 1 copy - you don't need a copy at every location
in the stack, and on every different instance that "shares" the
values.

Reflection / ComponentModel maintenance on structs is also just a
nightmare.

If these structs are the exact same structs that you pass to external
code, then fine - it might be necessary - but it doesn't sound like
it. In fact, if you actually have a dictionary under the hood then
things are even more complicated, and you have something that is
neither (semantic-wise) reference-type nor value-type. Personally I
don't think that this setup will do you any favors...

I'll have a look at the rest of the code (a bit later), and see what I
can see...

Marc
Jun 27 '08 #8
well ive swapped and changed a bit from structs and classes for
a few things, but definatly there are some unavoidable structs,
wich I have to deal with anyway. so the argument about wich is
best is a moot point.

yes structs is a nightmare but I have a decent solution,
as long as you can hold an instance of the outermost
object, and hold a list of FieldInfos describing the path
down to the item to edit you can do it relativly easily.
with typedreference and setvaluedirect.

I have just found that when the popup selection editor
calls my TypeConverter GetProperties() it gets passed
a value of SelectionWrapper instead of the actual value
wich is confusing me becuase I look at the value to
get the field dictionary, although I can find it in the wrapper probably.

I was trying to keep all the code to one class
and reduce the number of classes,
I have discovered you can simply add a converter attribute
to a type at runtime, instead of the going through
the TypeDescriptorProvider. ive also found the
pop up editor was calling the CustomTypeDescriptor.GetProperties
even though I had directed it to the apropriate type converter,
although the SelectionWrapper confusion may have cuased this.
Colin =^.^=

"Marc Gravell" <ma**********@gmail.comwrote in message
news:56**********************************@34g2000h sh.googlegroups.com...
It is indeed the UITypeEditor that provides the elipsis [...] and the
popup collection editor; but there are actually several inbuilt
collection editors that just look the same - for example, you mention
arrays - ArrayEditor is a subclass of CollectionEditor with array-
specific load/save code.

You could provide your own CollectionEditor implementation?

Re the large structs - you mention speed; is this from benchmarking?
Because from a speed perspective, large structs are actually a bad
thing, since they clog up the stack and have to be blitted constantly.
It also makes it very hard to sensibly make changes (mutable structs =
bad). Classes would have a slightly bigger footprint overall
(references + object headers + data, instead of just data), but with
classes you only need 1 copy - you don't need a copy at every location
in the stack, and on every different instance that "shares" the
values.

Reflection / ComponentModel maintenance on structs is also just a
nightmare.

If these structs are the exact same structs that you pass to external
code, then fine - it might be necessary - but it doesn't sound like
it. In fact, if you actually have a dictionary under the hood then
things are even more complicated, and you have something that is
neither (semantic-wise) reference-type nor value-type. Personally I
don't think that this setup will do you any favors...

I'll have a look at the rest of the code (a bit later), and see what I
can see...

Marc

Jun 27 '08 #9
well ive managed to solve this problem I think :-

in my TypeConverter I just simply save the
ITypeDescriptorContext context parameter,
by passing it to my OwnPropertyDescriptor,
then when I update the value, I check
to see if the context has a property field and
then call the SetValue with my updated copy,
wich updates the array.

I may be able to make use of this parameter elsewhere
and combine several bits of code into one.

Colin =^.^=

"Marc Gravell" <ma**********@gmail.comwrote in message
news:56**********************************@34g2000h sh.googlegroups.com...
It is indeed the UITypeEditor that provides the elipsis [...] and the
popup collection editor; but there are actually several inbuilt
collection editors that just look the same - for example, you mention
arrays - ArrayEditor is a subclass of CollectionEditor with array-
specific load/save code.

You could provide your own CollectionEditor implementation?

Re the large structs - you mention speed; is this from benchmarking?
Because from a speed perspective, large structs are actually a bad
thing, since they clog up the stack and have to be blitted constantly.
It also makes it very hard to sensibly make changes (mutable structs =
bad). Classes would have a slightly bigger footprint overall
(references + object headers + data, instead of just data), but with
classes you only need 1 copy - you don't need a copy at every location
in the stack, and on every different instance that "shares" the
values.

Reflection / ComponentModel maintenance on structs is also just a
nightmare.

If these structs are the exact same structs that you pass to external
code, then fine - it might be necessary - but it doesn't sound like
it. In fact, if you actually have a dictionary under the hood then
things are even more complicated, and you have something that is
neither (semantic-wise) reference-type nor value-type. Personally I
don't think that this setup will do you any favors...

I'll have a look at the rest of the code (a bit later), and see what I
can see...

Marc

Jun 27 '08 #10
Yes, the ITypeDescriptorContext is very powerful and versatile.
PropertyGrid plays nicely, but be aware that not all TypeConverter use-
cases use it (it might be null, or any of the properties might be
null) - for example, data-binding to a TextBox might not provide a
context.

Fortunately, most of the "can you do this methods" also pass in the
context, so if you need the context, you can check it at this point,
and say "no" if you are missing something.

Marc
Jun 27 '08 #11
ok thanks, I think ive got all I need to know now,
I did have a read of the ITypeDescriptorContext
on msdn , and also read further on the PropertyDescriptor,
it seems theres quite a lot more involved in implementing than
I realised but I dont think its relevant to my needs.

However there is one thing that is still puzzling me greatly,
when the pop up collection editor calls my type converter
GetProperties(context,value,attributes) the value it is passed is a
CollectionEditor.CollectionEditorCollectionForm.Se lectionWrapper
and certainly not of the type of the convert its destined for,
this type i think is in fact hidden, theres certainly little info on it
anywhere
If you have any idea about this I would be very greatfull.

It is also passed in the same way in the call to GetValue/SetValue in my
custom propertyDescriptor, Fortunatly I have found I can resolve it by
casting it to a propertyDescriptor
and calling GetValue, wich then gets my actual object.

many thanks
Colin =^.^=

"Marc Gravell" <ma**********@gmail.comwrote in message
news:37**********************************@56g2000h sm.googlegroups.com...
Yes, the ITypeDescriptorContext is very powerful and versatile.
PropertyGrid plays nicely, but be aware that not all TypeConverter use-
cases use it (it might be null, or any of the properties might be
null) - for example, data-binding to a TextBox might not provide a
context.

Fortunately, most of the "can you do this methods" also pass in the
context, so if you need the context, you can check it at this point,
and say "no" if you are missing something.

Marc

Jun 27 '08 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: aido | last post by:
Hi all, I have bound a custom list object to a combo box's data source. This object implements the ITypedList interface and returns a PropertyDescriptorCollection to the fields in the list...
0
by: margoulin | last post by:
Hi, how can I get the defautl PropertyDescriptor of a basic type, lets say int ? Thanks, -Marc
3
by: Martin Montgomery | last post by:
I have, for example, a property called myProperty. I would like, when using a property grid to display the property name as "My Property". Is this possible. Is there an attribute etc Thank ...
1
by: Peter | last post by:
Hi i have a class eg. class Person { public string surname... public string phone.... }
0
by: Alx Sharp | last post by:
Hello group! I've created a collection class that implements ITypedList: class MyCollection : IBindingList, IList, ICollection, IEnumerable, ITypedList { PropertyDescriptorCollection...
5
by: Lance | last post by:
I want to expose properties of a class to a user via a PropertyGrid class. Some of the properties are of type System.IO.FileInfo. Ideally, an OpenFileDialog window would appear when the user...
1
by: tomb | last post by:
My CustomCollection has several events based on ListChanged collection management, when the ListChanged event is raised the ListChangedEventArgs.PropertyDescriptor property is always null. Any...
2
by: Marc Gravell | last post by:
::: Question: Does anyone know of a simple Control / UserControl implementation that hosts a UITypeEditor? Or the correct way to call PropertyDescriptor.GetEditor() and get a non-null result for...
2
by: Tugrul HELVACI | last post by:
I'm using Delphi 2006 and I have a class defination like this: TPerson = class fPersonName : String; fPersonSurName : String; fPersonAge : Integer; published property PersonName : String...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.