您可以在此处参考 Marc Gravell 的示例。
Data binding dynamic data
我不得不调整其他人的代码以使下拉菜单正常工作,如果这不是一个完整的列表,我深表歉意。
您的自定义类的 GetConverter() 方法应该只返回 TypeDescriptor.GetConverter(this, true)。
如果您不知道,您的自定义类的动态属性将无法与 DataGridView 一起使用,因为 DGV 读取它们的方式。所以我这里的实现仅限于PropertyGrid。 Trying to use DataGridView together with ICustomTypeDescriptor
决定 PropertyGrid 组合框是否应该是可编辑的。 How do I add an editable combobox to a System.Windows.Forms.PropertyGrid?
// also necessary to make propertyInfo work
// this allows us to assign lists to propertyGrid dropdowns
[TypeConverter(typeof(PrebuiltListConverter))]
public class DecoratedDropdown { }
public class PrebuiltListConverter : StringConverter
{
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
CvarPropertyDescriptor descriptor = (CvarPropertyDescriptor)context.PropertyDescriptor;
return new StandardValuesCollection(descriptor.Options);
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { return true; }
// credit Zlatko; return false in StringConverter subclass to make editable combobox
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) { return false; }
}
- 您的自定义 PropertyDescriptor 需要保留对您的自定义属性的引用(例如下面的 m_Property)。它还必须重写 PropertyType 以返回与 A) 没有下拉列表时自定义类的类型相关联的类型,或 B) 您的 StringConverter 的下拉装饰子类。
public override Type PropertyType { get { return m_Property.Type; } }
我在我的自定义属性类上使用 Type 属性来做出决定:
public Type Type
{
get
{
if (IsDropDownEnabled)
return typeof(DecoratedDropdown);
else
return typeof(this);
}
}
- PropertyDescriptor 需要动态返回该属性的可选值列表,这是我存储在自定义属性类中的列表。我无法告诉你用 List 表示可选值是否有效。
public ICollection Options { get { dynamic dObj = m_Property; return dObj.PossibleValues; } }
- 您的自定义类需要具有完整的 TypeDescriptor 实现。
public String GetClassName() { return TypeDescriptor.GetClassName(this, true); }
public AttributeCollection GetAttributes() { return TypeDescriptor.GetAttributes(this, true); }
public String GetComponentName() { return TypeDescriptor.GetComponentName(this, true); }
public TypeConverter GetConverter() { return TypeDescriptor.GetConverter(this, true); }
public EventDescriptor GetDefaultEvent() { return TypeDescriptor.GetDefaultEvent(this, true); }
public PropertyDescriptor GetDefaultProperty() { return TypeDescriptor.GetDefaultProperty(this, true); }
public object GetEditor(Type editorBaseType) { return TypeDescriptor.GetEditor(this, editorBaseType, true); }
public EventDescriptorCollection GetEvents(Attribute[] attributes) { return TypeDescriptor.GetEvents(this, attributes, true); }
public EventDescriptorCollection GetEvents() { return TypeDescriptor.GetEvents(this, true); }
// GetProperties(Attribute[] attributes) etc.
public PropertyDescriptorCollection GetProperties() { return TypeDescriptor.GetProperties(this, true); }
public object GetPropertyOwner(PropertyDescriptor pd) { return this; }
如果我错过了什么,请告诉我。我最近做了这个。