C#实现非枚举类型的在属性控件中可下拉选择(二)

前言:相较于之前文章,用这种方式优点是可以修改在属性控件上显示的效果,然后重新绑定就可以了

1.效果图 

 2.使用举例

PropertyGridProperty propertyGridProperty = new PropertyGridProperty();

Property p1 = new Property("自定义", "名称", "Name", "", "Bridge", false, true);
p1.Converter = new DropDownListConverter("Bridge", "Hani", "Jodan");
propertyGridProperty.Add(p1);

Property p2 = new Property("自定义", "年龄", "Age", "", 100, false, true);
propertyGridProperty.Add(p2);

Property p3 = new Property("自定义", "籍贯", "Location", "", "sz", false, true);
p3.Converter = new DropDownListConverter("sz", "gz", "bj");
propertyGridProperty.Add(p3);

this.propertyGrid1.SelectedObject = propertyGridProperty;

 3.属性类和类型转换器

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace AttributeTest
{
    /// <summary>
    /// PropertyGrid对应的类
    /// </summary>
    public class PropertyGridProperty : ICustomTypeDescriptor
    {
        List<Property> _listProperty = new List<Property>();

        public void Add(Property value)
        {
            if (value != null)
            {
                if (!_listProperty.Contains(value))
                {
                    _listProperty.Add(value);
                }
            }
        }

        public void Remove(Property value)
        {
            if (value != null && _listProperty.Contains(value))
            {
                _listProperty.Remove(value);
            }
        }

        public Property this[int index]
        {
            get
            {
                return _listProperty[index];
            }
            set
            {
                _listProperty[index] = value;
            }
        }

        public Property this[object name]
        {
            get
            {
                return _listProperty.FirstOrDefault(p => p.Name == name.ToString());
            }
            set
            {
                Property pre = _listProperty.FirstOrDefault(p => p.Name == name.ToString());
                pre = value;
            }
        }

        #region ICustomTypeDescriptor 成员
        public AttributeCollection GetAttributes()
        {
            return TypeDescriptor.GetAttributes(this, true);
        }
        public string GetClassName()
        {
            return TypeDescriptor.GetClassName(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);
        }
        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            PropertyDescriptor[] newProps = new PropertyDescriptor[_listProperty.Count];
            for (int i = 0; i < _listProperty.Count; i++)
            {
                Property prop = (Property)this[i];
                newProps[i] = new CustomPropertyDescriptor(ref prop, attributes);
            }
            return new PropertyDescriptorCollection(newProps);
        }
        public PropertyDescriptorCollection GetProperties()
        {
            return TypeDescriptor.GetProperties(this, true);
        }
        public object GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }
        #endregion
    }

    /// <summary>
    /// 属性类
    /// </summary>
    public class Property
    {

        public Property(string sCategory, string sDisplayName, string sName, string sDescription, object sValue, bool sReadonly, bool sVisible)
        {
            this.Category = sCategory;
            this.DisplayName = sDisplayName;
            this.Name = sName;
            this.Description = sDescription;
            this.Value = sValue;
            this.ReadOnly = sReadonly;
            this.Visible = sVisible;
        }

        /// <summary>
        /// 属性所属类别
        /// </summary>
        public string Category { get; set; }

        /// <summary>
        /// 属性显示名称
        /// </summary>
        public string DisplayName { get; set; }

        /// <summary>
        /// 属性名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// 属性值
        /// </summary>
        public object Value { get; set; }

        /// <summary>
        /// 是否为只读
        /// </summary>
        public bool ReadOnly { get; set; }

        /// <summary>
        /// 是否可见
        /// </summary>
        public bool Visible { get; set; }

        /// <summary>
        /// 类型转换器,在制作下拉列表时需要用到
        /// </summary>
        public TypeConverter Converter { get; set; }

        /// <summary>
        /// 属性编辑器
        /// </summary>
        public virtual object Editor { get; set; }
    }

    public class CustomPropertyDescriptor : PropertyDescriptor
    {
        Property _property;
        public CustomPropertyDescriptor(ref Property myProperty, Attribute[] attrs)
            : base(myProperty.Name, attrs)
        {
            _property = myProperty;
        }
        #region PropertyDescriptor 重写方法
        public override bool CanResetValue(object component)
        {
            return false;
        }
        public override Type ComponentType
        {
            get { return null; }
        }
        public override object GetValue(object component)
        {
            return _property.Value;
        }
        public override string Description
        {
            get { return _property.Description; }
        }
        public override string Category
        {
            get { return _property.Category; }
        }
        public override string DisplayName
        {
            get { return !string.IsNullOrWhiteSpace(_property.DisplayName) ? _property.DisplayName : _property.Name; }
        }
        public override bool IsReadOnly
        {
            get { return _property.ReadOnly; }
        }
        public override void ResetValue(object component)
        {
            //Have to implement
        }
        public override bool ShouldSerializeValue(object component)
        {
            return false;
        }
        public override void SetValue(object component, object value)
        {
            _property.Value = value;
        }
        public override TypeConverter Converter
        {
            get { return _property.Converter; }
        }
        public override Type PropertyType
        {
            get { return _property.Value.GetType(); }
        }
        public override object GetEditor(Type editorBaseType)
        {
            return _property.Editor == null ? base.GetEditor(editorBaseType) : _property.Editor;
        }
        #endregion
    }

    /// <summary>
    /// 下拉框类型转换器
    /// </summary>
    public class DropDownListConverter : StringConverter
    {
        object[] _objects;
        public DropDownListConverter(params object[] objects)
        {
            _objects = objects;
        }
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }
        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return true;//true下拉框不可编辑
        }
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            return new StandardValuesCollection(_objects);
        }
    }


}
原文地址:https://www.cnblogs.com/bridgew/p/12709056.html