C# Can';在PropertyGrid中不显示具有接口属性的类
目前,我正试图通过PropertyGrid配置一些类。现在,如果类将属性作为接口提供,那么在显示值(网格中的右侧)时会遇到一些问题。我想,因为网格使用反射,它将采用真实的类型,并使用它的正常方式来显示网格中的值。对于演示,只需使用下面的类层次结构,创建一个带有PropertyGrid的简单表单,并通过调用C# Can';在PropertyGrid中不显示具有接口属性的类,c#,winforms,.net-4.0,propertygrid,C#,Winforms,.net 4.0,Propertygrid,目前,我正试图通过PropertyGrid配置一些类。现在,如果类将属性作为接口提供,那么在显示值(网格中的右侧)时会遇到一些问题。我想,因为网格使用反射,它将采用真实的类型,并使用它的正常方式来显示网格中的值。对于演示,只需使用下面的类层次结构,创建一个带有PropertyGrid的简单表单,并通过调用 propertyGrid1.SelectedObject = new MyContainerClass(); 以下是课程: public class MyContainerClass {
propertyGrid1.SelectedObject = new MyContainerClass();
以下是课程:
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;
}
}
正如您所看到的,容器在所有三个属性中都使用相同的对象,但在网格中,您将在class属性和object属性上看到ToString()
文本,但在interface属性上看不到任何内容。此外,TypeConverter仅用于使用确切类型的属性
有没有办法让PropertyGrid在接口属性后面显示类的ToString()结果?最后,我解决了大多数情况下的这个问题: 出现此问题时,会导致
PropertyDescriptor
在其Converter
属性中返回正确的转换器,或者至少返回基类TypeConverter
,该基类至少会调用ToString()
进行可视化。对于定义为接口的属性,属性网格将获得一个,但通过查看备注部分
ReferenceConverter通常在站点组件或设计环境的上下文中使用。如果没有组件站点或可用的ITypeDescriptorContext,此转换器几乎没有用处
我们似乎真的对它有点用处。幸运的是,我已经在使用自己的PropertyDescriptor
,所以我所要做的就是重写描述符的Converter属性并更改为以下内容:
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;
}
}
需要对
ReferenceConverter
进行显式检查,因为用户可能通过属性上的属性定义了自己的TypeEditor,基本实现将自动遵守该属性。如果有人通过属性明确表示他喜欢ReferenceConverter,这只会导致问题,但我认为不必处理这种情况(但可以通过检查PropertyDescriptor的属性来处理)。最后,我解决了大多数情况下的此问题:
出现此问题时,会导致PropertyDescriptor
在其Converter
属性中返回正确的转换器,或者至少返回基类TypeConverter
,该基类至少会调用ToString()
进行可视化。对于定义为接口的属性,属性网格将获得一个,但通过查看备注部分
ReferenceConverter通常在站点组件或设计环境的上下文中使用。如果没有组件站点或可用的ITypeDescriptorContext,此转换器几乎没有用处
我们似乎真的对它有点用处。幸运的是,我已经在使用自己的PropertyDescriptor
,所以我所要做的就是重写描述符的Converter属性并更改为以下内容:
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;
}
}
需要对ReferenceConverter
进行显式检查,因为用户可能通过属性上的属性定义了自己的TypeEditor,基本实现将自动遵守该属性。如果有人通过属性显式地说他喜欢ReferenceConverter,这只会导致问题,但我认为不必处理这种情况(但可以通过检查PropertyDescriptor的属性)