property subclass

  • Thread starter Thread starter rb
  • Start date Start date
R

rb

Hi,

I extended one of the standard controls by adding a new property, which is
also a class itself. I got everything going nicely in PropertyGrid except
for 2 things:

1. As soon as I drop this control on a form, the subclass-property doesn't
get instantiated as expected. For example, the Size property is normally
initiated as TheControl.Size = new System.Drawing.Size( xx, yy). My property
is initalized as follows:
MyProp prop1 = new MyPropType();
TheControl.MyProp = prop1;
prop1.MinValue = xx;
prop2.MaxValue = yy;

Seems that this happens because I use a default constructor ( MyProp() ).
However, if I remove the default constructor and leave only MyProp( min,
max ), I still don't get TheControl.MyProp = new MyProp and changes in
PropertyGrid don't persist.

2. Is there any way to order subclass properties when they're expanded in
PropertyGrid? I have MinValue and MaxValue properties but Max always comes
above Min (alpha sort order).

Thanks a lot.

rb
 
1: To use a non-default ctor, you need to provide a type-converter
that re-implements GetPropertiesSupported, GetProperties and
CreateInstance. To be honest, this is mainly useful for structs (since
almost all structs are immutable) - so for a (mutable) class I
probably wouldn't bother with this (and designer code is designer
code...). Especially with C# 3 on the horizon (with object-
initializers), non-defauly ctors (just to initialize different sub-
properties) get less and less attractive.

2: The alphabet is the alphabet. So no; not without fudging the names.

Marc
 
I just realized that the var designer uses to assign value to MyProp is
internal to InitializeComponents(). I was merely concerned that such vars
would also be public - and that would be just silly.

Thanks a lot for your time, Marc.

rb
 
No problem

Note: on the train I realized that there were 2 errors in my origianl
reply (not enough caffeine):

a: you *can* change the order by simply re-ordering in the
type-converter - example at foot

b: the TypeConverter does not affect editor serialization; for that I
suspect you need to provide a CodeDomSerializer via
DesignerSerializerAttribute. I also suspect that it is simply too much
mess to be worth it. If you can live with the local-variable in the
designer code, I'd go with the simple approach.

(for info, the CreateInstance is used to rebuild objects that have
read-only properties, but where the parent is settable)

Marc

Re-ordering example:

[TypeConverter(typeof(TestConverter))]
public class TestType {
public override string ToString() {
return string.Format("{0}-{1}", MinValue, MaxValue);
}
public TestType(int minValue, int maxValue)
//: this() // needed if struct
{
MinValue = minValue;
MaxValue = maxValue;
}
// private set to force ctor usage ;-p
public int MinValue { get; private set; }
public int MaxValue { get; private set; }
}
public class TestConverter : TypeConverter {
public override bool
GetCreateInstanceSupported(ITypeDescriptorContext context) {
return true;
}
public override object CreateInstance(ITypeDescriptorContext
context, System.Collections.IDictionary propertyValues) {
return new TestType((int)propertyValues["MinValue"],
(int)propertyValues["MaxValue"]);
}
public override bool
GetPropertiesSupported(ITypeDescriptorContext context) {
return true;
}
public override PropertyDescriptorCollection
GetProperties(ITypeDescriptorContext context, object value,
Attribute[] attributes) {
return TypeDescriptor.GetProperties(typeof(TestType),
attributes)
.Sort(new[] { "MinValue", "MaxValue" });
}
}
 
Marc Gravell said:
No problem

Note: on the train I realized that there were 2 errors in my origianl
reply (not enough caffeine):

a: you *can* change the order by simply re-ordering in the
type-converter - example at foot

b: the TypeConverter does not affect editor serialization; for that I
suspect you need to provide a CodeDomSerializer via
DesignerSerializerAttribute. I also suspect that it is simply too much
mess to be worth it. If you can live with the local-variable in the
designer code, I'd go with the simple approach.

Actually the TypeConverter does control editor serialization. You have to
handle a destination type of
System.ComponentModel.Design.Serialization.InstanceDescriptor in your
ConvertTo method.
(for info, the CreateInstance is used to rebuild objects that have
read-only properties, but where the parent is settable)

Marc

Re-ordering example:

[TypeConverter(typeof(TestConverter))]
public class TestType {
public override string ToString() {
return string.Format("{0}-{1}", MinValue, MaxValue);
}
public TestType(int minValue, int maxValue)
//: this() // needed if struct
{
MinValue = minValue;
MaxValue = maxValue;
}
// private set to force ctor usage ;-p
public int MinValue { get; private set; }
public int MaxValue { get; private set; }
}
public class TestConverter : TypeConverter {
public override bool
GetCreateInstanceSupported(ITypeDescriptorContext context) {
return true;
}
public override object CreateInstance(ITypeDescriptorContext
context, System.Collections.IDictionary propertyValues) {
return new TestType((int)propertyValues["MinValue"],
(int)propertyValues["MaxValue"]);
}
public override bool GetPropertiesSupported(ITypeDescriptorContext
context) {
return true;
}
public override PropertyDescriptorCollection
GetProperties(ITypeDescriptorContext context, object value, Attribute[]
attributes) {
return TypeDescriptor.GetProperties(typeof(TestType),
attributes)
.Sort(new[] { "MinValue", "MaxValue" });
}
}
 
Ah - thanks for the reminder; my first instinct wsan't far wrong then,
I had just forgotten about InstanceDescriptor... (annoyingly I have
done this before, but couldn't find the sample...)

However, I'm still inclined to say it isn't worth it ;-p
(at least, for cases like here where it is simply an aide, not a
necessity)

Cheers again,

Marc
 
Back
Top