问题
Currently i'm trying to configure some of my classes through the PropertyGrid. Now i have some problems about showing the value (the right side within the grid) if the class provides the property as an interface. I thought, cause the grid uses reflection it would take the real type and uses it's normal ways on showing the value within the grid. For a demonstration simply take the class hierarchy below and create a simple form with a PropertyGrid and put the object into it by calling
propertyGrid1.SelectedObject = new MyContainerClass();
Here are the classes:
public class MyContainerClass
{
// Simple properties that should be shown in the PropertyGrid
public MyInterface MyInterface { get; set; }
public MyClass MyClass { get; set; }
public object AsObject { get; set; }
public MyContainerClass()
{
// Create one instance of MyClass
var myClass = new MyClass();
// Put the instance into both properties
// (cause MyClass implements MyInterface)
MyClass = myClass;
MyInterface = myClass;
// and show it if it is declared as "object"
AsObject = myClass;
}
}
// Some kind of interface i'd like to show in the PropertyGrid.
public interface MyInterface
{
string Name { get; set; }
}
// A class that also implements the interface
// and uses some kind of TypeConverter
[TypeConverter(typeof(ExpandableObjectConverter))]
public class MyClass : MyInterface
{
// Create an instance and put something meaningful into the property.
public MyClass()
{
Name = "MyName";
}
public string Name { get; set; }
// Override ToString() to get something shown
// as value in the PropertyGrid.
public override string ToString()
{
return "Overridden ToString(): " + Name;
}
}
As you can see the container uses the same object in all three properties, but within the grid you'll see the ToString()
text on the class property and on the object property, but nothing on the interface property. Also the TypeConverter is only used on the property that uses the exact type.
PropertyGrid showing MyContainer http://image-upload.de/image/O2CC5e/9558e4e179.png
Exists there any way to let the PropertyGrid showing the ToString() result of the class behind the interface property?
回答1:
Finally i solved this problem for the most cases:
The problem occurs, cause the PropertyDescriptor
returns within its Converter
property normally the correct converter or at least the base class TypeConverter
which will at least call ToString()
for visualization. In case of a property that is defined as an interface the property grid will get a ReferenceConverter, but by looking into the remarks section
The ReferenceConverter is typically used within the context of sited components or a design environment. Without a component site or a usable ITypeDescriptorContext, this converter is of little use.
We really seem to have a little use for it. Fortunately i'm already using my own PropertyDescriptor
, so all i had to do was to override the Converter property of my descriptor and change to the following:
public override TypeConverter Converter
{
get
{
var converter = base.Converter;
// If the property of the class is a interface, the default implementation
// of PropertyDescriptor will return a ReferenceConverter, but that doesn't
// work as expected (normally the right site will stay empty).
// Instead we'll return a TypeConverter, that works on the concrete type
// and returns at least the ToString() result of the given type.
if (_OriginalPropertyDescriptor.PropertyType.IsInterface)
{
if (converter.GetType() == typeof(ReferenceConverter))
{
converter = _InterfaceConverter;
}
}
return converter;
}
}
The explicit check for the ReferenceConverter
is needed, cause it could be possible that the user defined its own TypeEditor through an attribute on the property, which will be automatically respected by the base implementation. It would only lead to problems if someone would explicit say through the attribute, that he likes the ReferenceConverter, but i don't think that case has to be handled (but could be by checking the attributes of the PropertyDescriptor).
来源:https://stackoverflow.com/questions/8532719/cant-show-class-with-interface-properties-in-propertygrid