首页 > 解决方案 > 如何使用自定义属性在 propertygrid 中添加动态组合框属性?

问题描述

我必须根据某些操作在 propertygrid 中创建一些动态属性。我可以按照https://www.codeproject.com/Articles/9280/Add-Remove-Items-to-from-PropertyGrid-at-Runtime示例创建动态属性。但我还需要在 propertygrid 中添加一个组合框。为此,我创建了一个从 stringConverter 派生的类。如下所示:

 public class FormatStringConverter : StringConverter
{
    public override Boolean GetStandardValuesSupported(ITypeDescriptorContext context) { return true; }
    public override Boolean GetStandardValuesExclusive(ITypeDescriptorContext context) { return true; }
    public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        List<String> list = new List<String>();
        list.Add("DepartmentA");        
        list.Add("DepartmentB");                
        list.Add("DepartmentC");
        return new StandardValuesCollection(list);
    }
}

但是在示例的 customClass 中,我应该返回什么以在 propertygrid 中将 stringConverters 值显示为组合框?

TypeConverter GetConverter()
{
   if(prop.Name == "department")
       //what to return here?
   else
       return TypeDescriptor.GetConverter(this, true);
}

如果有人使用其他 TypeConverters 解决了它,我会感谢它是否有助于我的事业。

标签: c#winformswpf-controlspropertygrid

解决方案


您可以在此处参考 Marc Gravell 的示例。 数据绑定动态数据 我不得不调整其他人的代码以使下拉菜单工作,如果这不是一个完整的列表,我深表歉意。

  1. 您的自定义类的 GetConverter() 方法应该只返回 TypeDescriptor.GetConverter(this, true)。

  2. 如果您不知道,您的自定义类的动态属性将无法与 DataGridView 一起使用,因为 DGV 读取它们的方式。所以我这里的实现仅限于PropertyGrid。尝试将 DataGridView 与 ICustomTypeDescriptor 一起使用

  3. 决定 PropertyGrid 组合框是否应该是可编辑的。如何将可编辑组合框添加到 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; }
    }
  1. 您的自定义 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);
        }
    }
  1. PropertyDescriptor 需要动态返回该属性的可选值列表,这是我存储在自定义属性类中的列表。我不能告诉你用 List 表示可选值是否有效。
    public ICollection Options { get { dynamic dObj = m_Property; return dObj.PossibleValues; } }
  1. 您的自定义类需要具有完整的 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; }

如果我错过了什么,请告诉我。我最近做了这个。


推荐阅读