您還可以使用ICustomTypeDescriptor過濾屬性列表。爲此,我爲數據對象(MyWrapper),自定義屬性描述符(MypropertyDescriptor)和集合類創建了一個包裝類。我擴展了集合類來觀察IList,以便可以修改數據,ITypedList使數據網格可以構建列。您可能還想要繼承ObservableCollection>或BindingList> <>。
自定義描述符是處理設置和檢索屬性值:
public sealed class MyPropertyDescriptor : System.ComponentModel.PropertyDescriptor
{
private PropertyDescriptor innerProperty;
private Boolean isReadonly;
public MyPropertyDescriptor(PropertyDescriptor innerProperty, Boolean isReadonly)
: base(innerProperty.Name, GetAttributeArray(innerProperty.Attributes))
{
this.innerProperty = innerProperty;
this.isReadonly = isReadonly;
if (!isReadonly) this.isReadonly = innerProperty.IsReadOnly;
}
public override Type ComponentType
{
get { return this.innerProperty.ComponentType; }
}
public override Boolean IsReadOnly
{
get { return this.isReadonly; }
}
public override Type PropertyType
{
get { return this.innerProperty.PropertyType; }
}
public override String Name
{
get
{
return this.innerProperty.Name;
}
}
public override String DisplayName
{
get
{
return this.innerProperty.DisplayName;
}
}
public override Boolean SupportsChangeEvents
{
get
{
return true;
}
}
public override void SetValue(Object component, Object value)
{
if (!this.isReadonly)
{
this.innerProperty.SetValue(component, value);
if (component is MyWrapper) (component as MyWrapper).NotifyPropertyChanged(this.innerProperty.Name);
}
}
public override Object GetValue(Object component)
{
return this.innerProperty.GetValue(component);
}
public override Boolean CanResetValue(Object component)
{
return false;
}
public override void ResetValue(Object component)
{
}
public override Boolean ShouldSerializeValue(Object component)
{
return true;
}
private static Attribute[] GetAttributeArray(AttributeCollection attributes)
{
List<Attribute> attr = new List<Attribute>();
foreach (Attribute a in attributes) attr.Add(a);
return attr.ToArray();
}
}
包裝類是控制通過ICustomTypeDescriptor來訪問屬性:
public sealed class MyWrapper : System.ComponentModel.ICustomTypeDescriptor, System.ComponentModel.INotifyPropertyChanged
{
private Object innerObject;
private String[] hiddenProps;
private String[] readonlyProps;
private Type innerType;
public MyWrapper(Object innerObject, String[] hiddenProps, String[] readonlyProps)
: base()
{
this.innerObject = innerObject;
this.hiddenProps = hiddenProps;
this.readonlyProps = readonlyProps;
this.innerType = innerObject.GetType();
}
public static PropertyDescriptorCollection FilterProperties(PropertyDescriptorCollection pdc, String[] hiddenProps, String[] readonlyProps)
{
List<PropertyDescriptor> list = new List<PropertyDescriptor>();
foreach (PropertyDescriptor pd in pdc)
{
if (hiddenProps != null)
{
Boolean isHidden = false;
foreach (String hidden in hiddenProps)
{
if (hidden.Equals(pd.Name, StringComparison.OrdinalIgnoreCase))
{
isHidden = true;
break;
}
}
if (isHidden) continue; // skip hidden
}
Boolean isReadonly = false;
if (readonlyProps != null)
{
foreach (String rp in readonlyProps)
{
if (rp.Equals(pd.Name, StringComparison.OrdinalIgnoreCase))
{
isReadonly = true;
break;
}
}
}
list.Add(new MyPropertyDescriptor(pd, isReadonly));
}
return new PropertyDescriptorCollection(list.ToArray());
}
#region ICustomTypeDescriptor Members
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
return FilterProperties(TypeDescriptor.GetProperties(this.innerType, attributes), hiddenProps, readonlyProps);
}
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{
return FilterProperties(TypeDescriptor.GetProperties(this.innerType), hiddenProps, readonlyProps);
}
AttributeCollection ICustomTypeDescriptor.GetAttributes()
{
return TypeDescriptor.GetAttributes(this.innerType);
}
String ICustomTypeDescriptor.GetClassName()
{
return TypeDescriptor.GetClassName(this.GetType());
}
String ICustomTypeDescriptor.GetComponentName()
{
return TypeDescriptor.GetComponentName(this.GetType());
}
TypeConverter ICustomTypeDescriptor.GetConverter()
{
return TypeDescriptor.GetConverter(this.GetType());
}
EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this.GetType());
}
PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
{
return null;
}
Object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(this.GetType(), editorBaseType);
}
EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
{
return null;
}
EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
{
return null;
}
Object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
{
return this.innerObject;
}
#endregion
#region INotifyPropertyChanged Members
internal void NotifyPropertyChanged(String propertyName)
{
if (this.propertyChanged != null) this.propertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private event PropertyChangedEventHandler propertyChanged;
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
add { propertyChanged += value; }
remove { propertyChanged -= value; }
}
#endregion
}
和修改後的版本的CollectionView <>。該示例的大部分內容僅將接口方法映射到內部列表。
public sealed class CollectionView<T> : IEnumerable<MyWrapper>, System.Collections.IList, IList<MyWrapper>, ITypedList
{
private String[] hiddenProps;
private String[] readonlyProps;
private List<MyWrapper> collection;
public CollectionView(IEnumerable<T> innerCollection, String[] hiddenProps, String[] readonlyProps)
: base()
{
this.hiddenProps = hiddenProps;
this.readonlyProps = readonlyProps;
this.collection = new List<MyWrapper>();
foreach (T item in innerCollection)
{
this.collection.Add(new MyWrapper(item, hiddenProps, readonlyProps));
}
}
#region ITypedList Members
PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
{
return MyWrapper.FilterProperties(TypeDescriptor.GetProperties(typeof(T)), this.hiddenProps, this.readonlyProps);
}
String ITypedList.GetListName(PropertyDescriptor[] listAccessors)
{
return null;
}
#endregion
#region IEnumerable<MyWrapper> Members
IEnumerator<MyWrapper> IEnumerable<MyWrapper>.GetEnumerator()
{
return this.collection.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.collection.GetEnumerator();
}
#endregion
#region IList Members
Int32 System.Collections.IList.Add(Object value)
{
return (this.collection as System.Collections.IList).Add(value);
}
void System.Collections.IList.Clear()
{
(this.collection as System.Collections.IList).Clear();
}
Boolean System.Collections.IList.Contains(Object value)
{
return (this.collection as System.Collections.IList).Contains(value);
}
Int32 System.Collections.IList.IndexOf(Object value)
{
return (this.collection as System.Collections.IList).IndexOf(value);
}
void System.Collections.IList.Insert(Int32 index, Object value)
{
(this.collection as System.Collections.IList).Insert(index, value);
}
Boolean System.Collections.IList.IsFixedSize
{
get { return (this.collection as System.Collections.IList).IsFixedSize; }
}
Boolean System.Collections.IList.IsReadOnly
{
get { return (this.collection as System.Collections.IList).IsReadOnly; }
}
void System.Collections.IList.Remove(Object value)
{
(this.collection as System.Collections.IList).Remove(value);
}
void System.Collections.IList.RemoveAt(Int32 index)
{
(this.collection as System.Collections.IList).RemoveAt(index);
}
Object System.Collections.IList.this[Int32 index]
{
get
{
return (this.collection as System.Collections.IList)[index];
}
set
{
(this.collection as System.Collections.IList)[index] = value;
}
}
#endregion
#region ICollection Members
void System.Collections.ICollection.CopyTo(Array array, Int32 index)
{
(this.collection as System.Collections.ICollection).CopyTo(array, index);
}
Int32 System.Collections.ICollection.Count
{
get { return (this.collection as System.Collections.ICollection).Count; }
}
Boolean System.Collections.ICollection.IsSynchronized
{
get { return (this.collection as System.Collections.ICollection).IsSynchronized; }
}
Object System.Collections.ICollection.SyncRoot
{
get { return (this.collection as System.Collections.ICollection).SyncRoot; }
}
#endregion
#region IList<MyWrapper> Members
Int32 IList<MyWrapper>.IndexOf(MyWrapper item)
{
return this.collection.IndexOf(item);
}
void IList<MyWrapper>.Insert(Int32 index, MyWrapper item)
{
this.collection.Insert(index, item);
}
void IList<MyWrapper>.RemoveAt(Int32 index)
{
this.collection.RemoveAt(index);
}
MyWrapper IList<MyWrapper>.this[Int32 index]
{
get
{
return this.collection[index];
}
set
{
this.collection[index] = value;
}
}
#endregion
#region ICollection<MyWrapper> Members
void ICollection<MyWrapper>.Add(MyWrapper item)
{
this.collection.Add(item);
}
void ICollection<MyWrapper>.Clear()
{
this.collection.Clear();
}
Boolean ICollection<MyWrapper>.Contains(MyWrapper item)
{
return this.collection.Contains(item);
}
void ICollection<MyWrapper>.CopyTo(MyWrapper[] array, Int32 arrayIndex)
{
this.collection.CopyTo(array, arrayIndex);
}
Int32 ICollection<MyWrapper>.Count
{
get { return this.collection.Count; }
}
Boolean ICollection<MyWrapper>.IsReadOnly
{
get { return false; }
}
Boolean ICollection<MyWrapper>.Remove(MyWrapper item)
{
return this.collection.Remove(item);
}
#endregion
}