【问题标题】:WPF Propertygrid with custom sorting具有自定义排序的 WPF Propertygrid
【发布时间】:2013-04-25 12:03:17
【问题描述】:

我正在为我的 WPF 项目寻找一个 PropertyGrid,它允许我自定义列出的属性/类别的顺序。现在我正在使用Extended WPF Toolkits(社区版)PropertyGrid 和CustomPropertyDescriptors。我的研究表明,无法使用该 PropertyGrid 进行自定义排序。

有(最好是免费的)解决方案吗?

【问题讨论】:

  • 什么?我用大约 20 行 XAML 和 30 行 C# 代码在不到一个小时的时间内创建了自己的属性网格。我不知道你在说什么。
  • 你很幸运!任何提示如何开始?您是否使用 DataGrid 作为基础?

标签: wpf propertygrid


【解决方案1】:

扩展 WPF 工具包中的属性排序可以通过使用 PropertyOrderAttribute 属性装饰属性来实现。

如果您不想通过在设计时用属性装饰 POCO 来污染 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

【讨论】:

    猜你喜欢
    • 2012-03-08
    • 2012-08-07
    • 2018-08-05
    • 1970-01-01
    • 1970-01-01
    • 2016-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多