private void Form_Main_Load(object sender, Event e)
{
PropertyMangeCus pmc = new PropertyMangeCus();
Property pp = new Property("ID", "1", false, true);
pp.Category = "基本信息";
pp.DisplayName = "我的ID";
pp.Editor = new EditorDropdownList();
pmc.Add(pp);
//string[] s = new string[] { "1", "2", "3", "4" };
//Property pp = new Property("ID", "7", false, true);
//pp.Category = "基本信息";
//pp.DisplayName = "我的ID";
//pp.Converter = new DropdownListConverter(s); //Property的Converter属性就可以设置类型转换
//pmc.Add(pp);
Property pIniPath = new Property("_iniPath", "", false, true);
pIniPath.Category = "基本信息";
pIniPath.DisplayName = "ini路径";
pIniPath.Editor = new PropertyFileItem(); //Property的Editor属性就可以设置属性编辑
pmc.Add(pIniPath);
propertyGrid1.SelectedObject = pmc;
}
public class Property
{
private string _name = string.Empty;
private object _value = null;
private bool _readonly = false;
private bool _visible = true;
private string _category = string.Empty;
private string _description = string.Empty;
TypeConverter _converter = null;
object _editor = null;
private string _displayname = string.Empty;
public Property(string sName, object sValue)
{
this._name = sName;
this._value = sValue;
}
public Property(string sName, object sValue, bool sReadonly, bool sVisible)
{
this._name = sName;
this._value = sValue;
this._readonly = sReadonly;
this._visible = sVisible;
}
public string Name //获得属性名
{
get { return _name; }
set { _name = value; }
}
public string Description
{
get { return _description; }
set { _description = value; }
}
public string DisplayName //属性显示名称
{
get
{
return _displayname;
}
set
{
_displayname = value;
}
}
public TypeConverter Converter //类型转换器,我们在制作下拉列表时需要用到
{
get
{
return _converter;
}
set
{
_converter = value;
}
}
public string Category //属性所属类别
{
get
{
return _category;
}
set
{
_category = value;
}
}
public object Value //属性值
{
get
{
return _value;
}
set
{
_value = value;
}
}
public bool ReadOnly //是否为只读属性
{
get
{
return _readonly;
}
set
{
_readonly = value;
}
}
public bool Visible //是否可见
{
get
{
return _visible;
}
set
{
_visible = value;
}
}
public virtual object Editor //属性编辑器
{
get
{
return _editor;
}
set
{
_editor = value;
}
}
}
public class CustomPropertyDescriptor : PropertyDescriptor
{
Property m_Property;
public CustomPropertyDescriptor(ref Property myProperty, Attribute[] attrs) : base(myProperty.Name, attrs)
{
m_Property = myProperty;
}
#region PropertyDescriptor 重写方法
public override bool CanResetValue(object component) => false;
public override Type ComponentType => null;
public override object GetValue(object component) => m_Property.Value;
public override string Description => m_Property.Description.Equals("") ? m_Property.Name : m_Property.Description;
public override string Category => m_Property.Category;
public override string DisplayName
{
get
{
return m_Property.DisplayName != "" ? m_Property.DisplayName : m_Property.Name;
}
}
public override bool IsReadOnly => m_Property.ReadOnly;
public override void ResetValue(object component)
{
}
public override bool ShouldSerializeValue(object component) => false;
public override void SetValue(object component, object value) => m_Property.Value = value;
public override TypeConverter Converter => m_Property.Converter;
public override Type PropertyType => m_Property.Value.GetType();
public override object GetEditor(Type editorBaseType)
{
return m_Property.Editor == null ? base.GetEditor(editorBaseType) : m_Property.Editor;
}
#endregion
}
public class PropertyMangeCls:CollectionBase, ICustomTypeDescriptor
{
public void Add(Property value)
{
int flag = -1;
if(value != null)
{
if(base.List.Count > 0)
{
IList<Property> mList = new List<Property>();
for (int i = 0; i < base.List.Count; i++)
{
Property p = base.List[i] as Property;
if(value.Name == p.Name)
{
flag = i;
}
mList.Add(p);
}
if(flag == -1)
{
mList.Add(value);
}
base.List.Clear();
foreach(Property p in mList)
{
base.List.Add(p);
}
}
else
{
base.List.Add(value);
}
}
}
public void Remove(Property value)
{
if(value != null && base.List.Count > 0)
{
base.List.Remove(value);
}
}
public Property this[int index]
{
get
{
return (Property)base.List[index];
}
set
{
base.List[index] = (Property)value;
}
}
#region ICustomTypeDescriptor 成员
public object GetPropertyOwner(PropertyDescriptor pd) => this;
public string GetClassName() => TypeDescriptor.GetClassName(this, true);
public string GetComponentName() => TypeDescriptor.GetComponentName(this, true);
public AttributeCollection GetAttributes() => TypeDescriptor.GetAttributes(this, true);
public TypeConverter GetConverter() => TypeDescriptor.GetConverter(this, true);
public object GetEditor(Type editorBaseType) => TypeDescriptor.GetEditor(this, editorBaseType, true);
public EventDescriptor GetDefaultEvent() => TypeDescriptor.GetDefaultEvent(this, true);
public EventDescriptorCollection GetEvents() => TypeDescriptor.GetEvents(this, true);
public EventDescriptorCollection GetEvents(Attribute[] attributes) => TypeDescriptor.GetEvents(this, attributes, true);
public PropertyDescriptor GetDefaultProperty() => TypeDescriptor.GetDefaultProperty(this, true);
public PropertyDescriptorCollection GetProperties() => TypeDescriptor.GetProperties(this, true);
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
PropertyDescriptor[] newProps = new PropertyDescriptor[this.Count];
for (int i = 0; i < this.Count; i++)
{
Property prop = (Property)this[i];
newProps[i] = new CustomPropertyDescriptor(ref prop, attributes);
}
return new PropertyDescriptorCollection(newProps);
}
#endregion
}
下拉框
public class EditorDropdownList : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
IWindowsFormsEditorService editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
if(editorService != null)
{
ListBox lb = new ListBox();
lb.Items.Add("1");
lb.Items.Add("2");
lb.Items.Add("3");
lb.Items.Add("4");
lb.Items.Add("5");
lb.Items.Add("6");
lb.SelectedIndexChanged += new System.EventHandler(lb_Click);
editorService.DropDownControl(lb);
value = lb.SelectedItem;
}
return base.EditValue(context, provider, value);
}
private void lb_Click(Object sender, EventArgs args)
{
ListBox lb = (ListBox)sender;
Form fm = lb.FindForm();
fm.Close();
}
}
文件选择器
public class PropertyFileItem:FileNameEditor
{
protected override void InitializeDialog(OpenFileDialog openFileDialog)
{
base.InitializeDialog(openFileDialog);
openFileDialog.Filter = "ini文件|*.ini";
}
}
文件选择器2
public class PropertyFileItem1:UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
if(edSvc != null)
{
//可以打开任何特定的对话框
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "ini(*.ini)|*.ini";
dialog.AddExtension = false;
if (dialog.ShowDialog().Equals(DialogResult.OK))
return dialog.FileName;
}
return value;
}
}
类型转换器
public class DropdownListConverter:StringConverter
{
object[] m_Objects;
public DropdownListConverter(object[] objects)
{
m_Objects = objects;
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true; //true 下拉框不可编辑
}
public override
System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
return new StandardValuesCollection(m_Objects); //我们可以直接在内部定义一个数组,但并不建议这样做,这样对于下拉框的灵活性有很大影响
}
}
代码主要参考如下文章,在此特意感谢两位分享。