带有自定义排序的WPF Propertygrid
我正在为我的WPF项目寻找一个PropertyGrid,它允许我自定义列出的属性/类别的顺序。现在我正在使用s(社区版)PropertyGrid和带有自定义排序的WPF Propertygrid,wpf,propertygrid,Wpf,Propertygrid,我正在为我的WPF项目寻找一个PropertyGrid,它允许我自定义列出的属性/类别的顺序。现在我正在使用s(社区版)PropertyGrid和CustomPropertyDescriptors。我的研究表明,使用该属性网格进行自定义排序是不可能的 是否有(最好是免费的)解决方案?扩展WPF工具包中的属性排序可以通过使用PropertyOrderAttribute属性装饰属性来实现 如果您不想在设计时用属性装饰POCO,或者顺序在某种程度上是动态的,那么可以通过创建类型转换器并重写GetPro
CustomPropertyDescriptor
s。我的研究表明,使用该属性网格进行自定义排序是不可能的
是否有(最好是免费的)解决方案?扩展WPF工具包中的属性排序可以通过使用PropertyOrderAttribute属性装饰属性来实现 如果您不想在设计时用属性装饰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);
}
}
}
使用Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
使用系统组件模型;
公共类MyExpandableIListConverter:ExpandableObjectConverter
{
公共重写属性描述或集合GetProperties(ITypeDescriptorContext上下文、对象值、属性[]属性)
{
if(值为IList)
{
IList list=作为IList的值;
PropertyDescriptorCollection propDescriptions=新的PropertyDescriptorCollection(null);
IEnumerator枚举器=list.GetEnumerator();
int计数器=-1;
while(枚举数.MoveNext())
{
计数器++;
添加(新的ListItemPropertyDescriptor(列表,计数器));
}
返回描述;
}
其他的
{
返回base.GetProperties(上下文、值、属性);
}
}
}
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();
}
使用Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
使用系统组件模型;
公共类ListItemPropertyDescriptor:PropertyDescriptor
{
私有只读IList所有者;
私有只读int索引;
公共ListItemPropertyDescriptor(IList所有者,int索引):基(“[”+索引+“]),null)
{
this.owner=所有者;
这个指数=指数;
}
公共覆盖属性集合属性
{
得到
{
var attributes=TypeDescriptor.GetAttributes(GetValue(null),false);
//如果未应用Xceed可扩展对象属性,则应用它
如果(!attributes.OfType().Any())
{
attributes=AddAttribute(新的ExpandableObjectAttribute(),attributes);
}
//设置xceed order属性
属性=添加属性(新属性或属性(索引),属性);
返回属性;
}
}
私有属性集合AddAttribute(属性newAttribute、属性集合oldAttributes)
{
属性[]新属性=新属性[oldAttributes.Count+1];
CopyTo(newAttributes,1);
newAttributes[0]=newAttribute;
返回新属性集合(newAttributes);
}
公共覆盖布尔CanResetValue(对象组件)
{
返回false;
}
公共覆盖对象GetValue(对象组件)
{
返回值;
}
私人T值
=>所有者[索引];
公共替代无效重置值(对象组件)
{
抛出新的NotImplementedException();
}
公共覆盖无效设置值(对象组件、对象值)
{
所有者[索引]=(T)值;
}
公共重写bool ShouldSerializeValue(对象组件)
{
返回false;
}
公共重写类型ComponentType
=>owner.GetType();
公共覆盖布尔为只读
=>假;
公共覆盖类型PropertyType
=>值?.GetType();
}
此代码的部分内容改编自扩展WPF工具包中的属性排序,可以通过使用PropertyOrderAttribute属性装饰属性来实现 如果您不想在设计时用属性装饰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);
}
}
}
使用Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
使用系统组件模型;
公共类MyExpandableIListConverter:ExpandableObjectConverter
{
公共重写属性描述或集合GetProperties(ITypeDescriptorContext上下文、对象值、属性[]属性)
{
if(值为IList)
{
IList list=作为IList的值;
PropertyDescriptorCollection propDescriptions=新的PropertyDescriptorCollection(null);
IEnumerator枚举器=list.GetEnumerator();
int计数器=-1;
while(枚举数.MoveNext())
{
计数器++;
添加(新的ListItemPropertyDescriptor(列表,计数器));
}
返回描述;
}
其他的
{
返回base.GetProperties(上下文、值、属性);
}
}
}
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();
}
使用Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
使用系统组件模型;
公共类ListItemPropertyDescriptor:PropertyDescriptor
{
私有只读IList所有者;
私有只读int索引;
公共ListItemPropertyDescriptor(IList所有者,int索引):基(“[”+索引+“]),null)
{
this.owner=所有者;
这个指数=指数;
}
公共覆盖属性集合属性
{
得到
{
var attributes=TypeDescriptor.GetAttributes(GetValue(null),false);
//如果“Xceed可扩展对象”属性为“否”