我正在为我的WPF项目寻找一个PropertyGrid,它允许我自定义列出属性/类别的顺序。现在我正在使用Extended WPF Toolkit(社区版)PropertyGrid和CustomPropertyDescriptor
s。我的研究表明,使用PropertyGrid进行自定义排序是不可能的。
是否有(最好是免费的)解决方案?
答案 0 :(得分:1)
可以通过使用PropertyOrderAttribute属性修饰属性来实现Extended WPF Toolkit中属性的排序。
如果你不想通过在设计时用属性修饰它们来污染POCO,或者命令在某种程度上是动态的,那么可以通过创建类型转换器并覆盖GetProperties方法在运行时添加属性。 。例如,如果您希望维护通用IList类型的索引顺序:
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using System.ComponentModel;
public class MyExpandableIListConverter<T> : ExpandableObjectConverter
{
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
if (value is IList<T>)
{
IList<T> list = value as IList<T>;
PropertyDescriptorCollection propDescriptions = new PropertyDescriptorCollection(null);
IEnumerator enumerator = list.GetEnumerator();
int counter = -1;
while (enumerator.MoveNext())
{
counter++;
propDescriptions.Add(new ListItemPropertyDescriptor<T>(list, counter));
}
return propDescriptions;
}
else
{
return base.GetProperties(context, value, attributes);
}
}
}
ListItemPropertyDescriptor的定义如下:
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using System.ComponentModel;
public class ListItemPropertyDescriptor<T> : PropertyDescriptor
{
private readonly IList<T> owner;
private readonly int index;
public ListItemPropertyDescriptor(IList<T> owner, int index) : base("["+ index+"]", null)
{
this.owner = owner;
this.index = index;
}
public override AttributeCollection Attributes
{
get
{
var attributes = TypeDescriptor.GetAttributes(GetValue(null), false);
//If the Xceed expandable object attribute is not applied then apply it
if (!attributes.OfType<ExpandableObjectAttribute>().Any())
{
attributes = AddAttribute(new ExpandableObjectAttribute(), attributes);
}
//set the xceed order attribute
attributes = AddAttribute(new PropertyOrderAttribute(index), attributes);
return attributes;
}
}
private AttributeCollection AddAttribute(Attribute newAttribute, AttributeCollection oldAttributes)
{
Attribute[] newAttributes = new Attribute[oldAttributes.Count + 1];
oldAttributes.CopyTo(newAttributes, 1);
newAttributes[0] = newAttribute;
return new AttributeCollection(newAttributes);
}
public override bool CanResetValue(object component)
{
return false;
}
public override object GetValue(object component)
{
return Value;
}
private T Value
=> owner[index];
public override void ResetValue(object component)
{
throw new NotImplementedException();
}
public override void SetValue(object component, object value)
{
owner[index] = (T)value;
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
public override Type ComponentType
=> owner.GetType();
public override bool IsReadOnly
=> false;
public override Type PropertyType
=> Value?.GetType();
}
此代码的部分内容是根据following SO answer
改编的