내가이 시점에 도달 한 방법에 대한 약간의 기록을 제공하겠습니다.PropertyGrid - IList에서 파생 한 속성 <T>, 사용자가 PropertyGrid에 항목을 추가/편집/제거 할 수 있도록 추가하려면 어떻게해야합니까?
원래 클래스에서 파생 된 CollectionsBase에서 파생 된 Property가 있었으며 PropertyGrid에 매핑 된이 컬렉션을 사용자가 목록에서 항목을 추가/편집/제거 할 수있었습니다.
그러나 CollectionsBase를 NHibernate로 매핑 할 수 없으므로 초기 구현을 스크랩해야하고 CollectionsBase에서 파생되는 대신 IList에서 파생 된 클래스를가집니다.
이제 NHibernate에 매핑 할 수 있지만 PropertyGrid를 통해 컬렉션을 편집 할 수 없습니다.
2 명이 서로 잘 어울리는 데 도움이 필요합니다.
public virtual ZoneCollection Zones
{
get { return zones; }
set { zones = value; }
}
내 구역은 다음과 같이 정의된다 IList의 상속 컬렉션 :
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;
}
}
}
을 이제 내은 ICustomTypeDescriptor 내 메인 클래스에서
는 I는 속성으로 정의 이 클래스가 CollectionsBase에서 파생되었을 때 PropertyDescriptor는 정상적으로 작동했지만 이제는 속성 이름에 "..."단추가없는 클래스 이름 ZoneCollection 만 표시됩니다. dd/편집/목록에서 항목을 제거하십시오.
IList에서 상속받은이 기능이 제대로 작동하지 않습니다. 무엇이 잘못 되었습니까?
[TypeConverter(typeof(ExpandableObjectConverter))]
ZoneCollection의 시작에, 내가 확장 가능한 트리에 나와있는 목록의 항목을 얻을 수 있지만, 내가 무엇을 찾고 아니에요 :
나는 추가합니다. 어디에서 "..."버튼을 클릭하면 CollectionBase 대신 IList에서 상속 받았을 때 컬렉션의 항목을 추가/편집/제거 할 수있는 팝업 창이 열렸습니까?
네,하지만 NHibernate에는 IList의 아닌 목록을 필요로한다. IList을 사용하여 non-gneric IList 구현을 사용하지 않았습니까? 또는 IList에서 파생 된 것으로 정의해야하고 내 목록을 특정 유형으로 설정해야합니까? –
@Nathan - 캐스트 (as, is)를 수행하는 코드의 경우 작동하지만 * 구현되지만 PropertyGrid 코드는 리플렉션을 사용하고 IList가 클래스에 의해 직접 구현되었는지 검사합니다. 제네릭 구현을 유지할 수 있지만 IList를 추가하고 구현해야합니다. –
좋습니다 IList에서 파생되는 대신 IList에서 파생되었습니다. ZonesCollection의 생성자에서 IList _list를 새 List ()과 동일하게 설정했습니다.이제 "..."버튼을 사용하여 PropertyGrid의 등록 정보 영역이 나열됩니다. 그러나 컬렉션 편집기에서 영역의 속성은 표시되지 않습니다. 어떤 아이디어? –