PropertyGrid -从IList派生的属性,我如何添加到PropertyGrid以便用户可以添加/编辑/删
本文关键字:添加 PropertyGrid 编辑 用户 IList 派生 属性 何添加 | 更新日期: 2023-09-27 18:08:56
让我提供一点关于我是如何达到这一点的历史。
我最初在我的类中有一个属性,它派生自CollectionsBase,并将这个集合映射到PropertyGrid,用户可以随意从列表中添加/编辑/删除项。
然而,我不能映射CollectionsBase与NHibernate,因此我不得不放弃我的初始实现,而不是从CollectionsBase派生,我有类从IList派生。
现在我可以映射到NHibernate,但我无法通过PropertyGrid编辑集合。
我需要一些帮助,让他们俩好好相处。
在我的主类我有一个属性定义为:
public virtual ZoneCollection Zones
{
get { return zones; }
set { zones = value; }
}
继承illist的My Zone Collection定义如下:
public class ZoneCollection : IList<Zone>, ICustomTypeDescriptor
{
private IList<Zone> _list;
public IList<Zone> _List
{
get { return _list; }
}
public ZoneCollection()
{
_list = new List<Zone>();
}
#region Implementation of IEnumerable
public IEnumerator<Zone> GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
#region Implementation of ICollection<Zone>
public void Add(Zone item)
{
_list.Add(item);
}
public void Clear()
{
_list.Clear();
}
public bool Contains(Zone item)
{
return _list.Contains(item);
}
public void CopyTo(Zone[] array, int arrayIndex)
{
_list.CopyTo(array, arrayIndex);
}
public bool Remove(Zone item)
{
return _list.Remove(item);
}
public int Count
{
get { return _list.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
#endregion
#region Implementation of IList<Zone>
public int IndexOf(Zone item)
{
return _list.IndexOf(item);
}
public void Insert(int index, Zone item)
{
_list.Insert(index, item);
}
public void RemoveAt(int index)
{
_list.RemoveAt(index);
}
public Zone this[int index]
{
get { return (Zone)_list[index]; }
set { _list[index] = value; }
}
#endregion
// Implementation of interface ICustomTypeDescriptor
#region ICustomTypeDescriptor impl
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);
}
public object GetPropertyOwner(PropertyDescriptor pd)
{
return this;
}
/// <summary>
/// Called to get the properties of this type. Returns properties with certain
/// attributes. this restriction is not implemented here.
/// </summary>
/// <param name="attributes"></param>
/// <returns></returns>
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return GetProperties();
}
/// <summary>
/// Called to get the properties of this type.
/// </summary>
/// <returns></returns>
public PropertyDescriptorCollection GetProperties()
{
// Create a collection object to hold property descriptors
PropertyDescriptorCollection pds = new PropertyDescriptorCollection(null);
// Iterate the list of zones
for (int i = 0; i < this._list.Count; i++)
{
// Create a property descriptor for the zone item and add to the property descriptor collection
ZoneCollectionPropertyDescriptor pd = new ZoneCollectionPropertyDescriptor(this, i);
pds.Add(pd);
}
// return the property descriptor collection
return pds;
}
#endregion
}
/// <summary>
/// Summary description for CollectionPropertyDescriptor.
/// </summary>
public class ZoneCollectionPropertyDescriptor : PropertyDescriptor
{
private ZoneCollection collection = null;
private int index = -1;
public ZoneCollectionPropertyDescriptor(ZoneCollection coll, int idx) :
base("#" + idx.ToString(), null)
{
this.collection = coll;
this.index = idx;
}
public override AttributeCollection Attributes
{
get
{
return new AttributeCollection(null);
}
}
public override bool CanResetValue(object component)
{
return true;
}
public override Type ComponentType
{
get
{
return this.collection.GetType();
}
}
public override string DisplayName
{
get
{
Zone zone = this.collection[index];
return zone.ID.ToString();
}
}
public override string Description
{
get
{
Zone zone = this.collection[index];
StringBuilder sb = new StringBuilder();
sb.Append(zone.ID.ToString());
if (zone.Streets.Route != String.Empty || zone.Streets.Crossing != String.Empty)
sb.Append("::");
if (zone.Streets.Route != String.Empty)
sb.Append(zone.Streets.Route);
if (zone.Streets.Crossing != String.Empty)
{
sb.Append(" and ");
sb.Append(zone.Streets.Crossing);
}
return sb.ToString();
}
}
public override object GetValue(object component)
{
return this.collection[index];
}
public override bool IsReadOnly
{
get { return false; }
}
public override string Name
{
get { return "#" + index.ToString(); }
}
public override Type PropertyType
{
get { return this.collection[index].GetType(); }
}
public override void ResetValue(object component)
{
}
public override bool ShouldSerializeValue(object component)
{
return true;
}
public override void SetValue(object component, object value)
{
// this.collection[index] = value;
}
}
}
现在,当这个类从CollectionsBase派生时,我的ICustomTypeDescriptor和PropertyDescriptor工作得很好,但是现在它只是在属性名称中显示类名ZoneCollection,而没有"…"按钮来添加/编辑/从列表中删除项。
我做错了什么,现在它是从IList继承的,这是不工作?
如果我添加:
[TypeConverter(typeof(ExpandableObjectConverter))]
在ZoneCollection的开头,我得到了在可展开树中列出的列表中的项目,但这不是我要寻找的。在哪里"…"按钮去,打开了一个弹出窗口,使我能够添加/编辑/删除项目的集合,当我从IList继承而不是CollectionBase?
PropertyGrid是一只脾气暴躁的老野兽。它需要非泛型的IList显式实现,而不是泛型的。
作为一个站点说明,您可以直接从List<Zone>
派生ZoneCollection,并且您不需要任何ICustomTypeDescriptor/PropertyDescriptor,关于这个PropertyGrid问题。
下面是一个看起来可行的实现:
public class ZoneCollection : IList<Zone>, IList
{
private List<Zone> _list = new List<Zone>();
public ZoneCollection()
{
}
public int IndexOf(Zone item)
{
return _list.IndexOf(item);
}
public void Insert(int index, Zone item)
{
_list.Insert(index, item);
}
public void RemoveAt(int index)
{
_list.RemoveAt(index);
}
public Zone this[int index]
{
get
{
return _list[index];
}
set
{
_list[index] = value;
}
}
public void Add(Zone item)
{
_list.Add(item);
}
public void Clear()
{
_list.Clear();
}
public bool Contains(Zone item)
{
return _list.Contains(item);
}
public void CopyTo(Zone[] array, int arrayIndex)
{
_list.CopyTo(array, arrayIndex);
}
public int Count
{
get { return _list.Count; }
}
public bool IsReadOnly
{
get { return ((IList)_list).IsReadOnly; }
}
public bool Remove(Zone item)
{
return _list.Remove(item);
}
public IEnumerator<Zone> GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
int IList.Add(object value)
{
int index = Count;
Add((Zone)value);
return index;
}
bool IList.Contains(object value)
{
return Contains((Zone)value);
}
int IList.IndexOf(object value)
{
return IndexOf((Zone)value);
}
void IList.Insert(int index, object value)
{
Insert(index, (Zone)value);
}
bool IList.IsFixedSize
{
get { return ((IList)_list).IsFixedSize; }
}
bool IList.IsReadOnly
{
get { return ((IList)_list).IsReadOnly; }
}
void IList.Remove(object value)
{
Remove((Zone)value);
}
object IList.this[int index]
{
get
{
return this[index];
}
set
{
this[index] = (Zone)value;
}
}
void ICollection.CopyTo(Array array, int index)
{
CopyTo((Zone[])array, index);
}
bool ICollection.IsSynchronized
{
get { return ((ICollection)_list).IsSynchronized; }
}
object ICollection.SyncRoot
{
get { return ((ICollection)_list).SyncRoot; }
}
}