2013-04-25 192 views
1

我正在爲我的WPF項目尋找一個PropertyGrid,使我可以自定義列出的屬性/類別的順序。現在我正在使用Extended WPF Toolkit s(Community Edition)PropertyGrid和CustomPropertyDescriptor s。我的研究表明,使用PropertyGrid進行自定義排序是不可能的。WPF Propertygrid與自定義排序

有沒有(最好是免費的)解決方案?

+0

什麼?我用不到一個小時的時間創建了自己的Property Grid,其中包含大約20行XAML和30行C#代碼。我不知道你在說什麼。 – 2013-04-26 14:55:24

+0

幸運啦!任何提示如何開始?你使用DataGrid作爲基礎嗎? – mamuesstack 2013-04-29 06:02:00

回答

1

通過使用PropertyOrderAttribute屬性修飾屬性,可以實現擴展WPF工具包中屬性的排序。

如果您不想通過在設計時用屬性裝飾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

適於