DevExpress PropertyGrid控件自定义:列表项替换索引为友好名称
解决DevExpress PropertyGrid集合项自定义显示名称的问题
嘿,你已经找对方向啦!实现ICustomTypeDescriptor确实是替换集合默认索引显示的核心思路,接下来咱们把这个方案落地,完善代码就能让PropertyGrid显示你想要的友好名称啦~
核心思路
PropertyGrid默认会用[0]、[1]这种索引来显示集合元素,我们需要通过自定义PropertyDescriptor,为每个集合元素返回你想要的友好名称,同时借助ICustomTypeDescriptor告诉PropertyGrid使用我们自定义的属性描述。
完整实现步骤
1. 自定义集合元素的PropertyDescriptor
首先创建一个继承自PropertyDescriptor的子类,重写DisplayName属性来返回友好名称,同时处理获取/设置集合元素的逻辑:
public class CollectionItemPropertyDescriptor : PropertyDescriptor { private readonly CustomObservableCollection _collection; private readonly int _index; public CollectionItemPropertyDescriptor(CustomObservableCollection collection, int index) : base($"Item_{index}", null) { _collection = collection; _index = index; } // 这里返回你想要的友好名称,比如从集合元素的某个属性获取 public override string DisplayName => _collection[_index].SheetName; // 假设你的ViewModel有SheetName属性 public override string Name => base.Name; public override bool IsReadOnly => false; public override Type ComponentType => typeof(CustomObservableCollection); public override Type PropertyType => typeof(PropertyGridWorkSheetViewModel); public override bool CanResetValue(object component) => false; public override object GetValue(object component) => _collection[_index]; public override void ResetValue(object component) { } public override void SetValue(object component, object value) { if (value is PropertyGridWorkSheetViewModel item) { _collection[_index] = item; } } public override bool ShouldSerializeValue(object component) => false; }
2. 完善CustomObservableCollection的ICustomTypeDescriptor实现
接下来补全你的CustomObservableCollection类,实现ICustomTypeDescriptor的关键方法,同时监听集合变化来通知PropertyGrid更新:
public class CustomObservableCollection : ObservableCollection<PropertyGridWorkSheetViewModel>, ICustomTypeDescriptor { public CustomObservableCollection() { // 监听集合变化,通知PropertyGrid刷新属性 CollectionChanged += (s, e) => { TypeDescriptor.Refresh(this); }; } // ICustomTypeDescriptor 实现 public AttributeCollection GetAttributes() => TypeDescriptor.GetAttributes(this, true); public string GetClassName() => TypeDescriptor.GetClassName(this, true); public string GetComponentName() => TypeDescriptor.GetComponentName(this, true); public TypeConverter GetConverter() => TypeDescriptor.GetConverter(this, true); public EventDescriptor GetDefaultEvent() => TypeDescriptor.GetDefaultEvent(this, true); public PropertyDescriptor GetDefaultProperty() => TypeDescriptor.GetDefaultProperty(this, true); public object GetEditor(Type editorBaseType) => TypeDescriptor.GetEditor(this, editorBaseType, true); public EventDescriptorCollection GetEvents() => TypeDescriptor.GetEvents(this, true); public EventDescriptorCollection GetEvents(Attribute[] attributes) => TypeDescriptor.GetEvents(this, attributes, true); // 重点:返回我们自定义的PropertyDescriptor集合 public PropertyDescriptorCollection GetProperties() => GetProperties(null); public PropertyDescriptorCollection GetProperties(Attribute[] attributes) { var properties = new List<PropertyDescriptor>(); for (int i = 0; i < Count; i++) { properties.Add(new CollectionItemPropertyDescriptor(this, i)); } return new PropertyDescriptorCollection(properties.ToArray()); } public object GetPropertyOwner(PropertyDescriptor pd) => this; }
3. 绑定到PropertyGrid
现在把你的CustomObservableCollection实例绑定到PropertyGrid的SelectedObject或者对应的属性上,PropertyGrid就会自动使用你定义的友好名称来显示每个集合项啦~
注意事项
- 如果你的集合元素的友好名称是动态变化的(比如用户修改了SheetName),需要在
PropertyGridWorkSheetViewModel中实现INotifyPropertyChanged,并且在CollectionItemPropertyDescriptor中监听属性变化,调用OnValueChanged来通知PropertyGrid更新显示。 - 确保
PropertyGridWorkSheetViewModel的属性是可访问的,这样PropertyDescriptor才能正确获取值。
内容的提问来源于stack exchange,提问作者Radu Olteanu
相关产品推荐
相关产品推荐

