2013-07-10 2 views
7

Есть ли способ сделать .NET FormsPropertyGrid уважать DisplayNameAttribute, когда он сортирует свойства нескольких выбранных объектов. Когда один объект выбирает сортировки PropertyGrid на основе DisplayNameAttribute, но при выборе нескольких объектов он использует фактическое имя свойства для сортировки..Net Forms PropertyGrid игнорирует DisplayNameAttribute при сортировке свойств для нескольких выбранных объектов

Следующий код демонстрирует проблему:

static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Form myForm1 = new Form(); 
     myForm1.Width = 820; 
     myForm1.Height = 340; 

     PropertyGrid grid1 = new PropertyGrid(); 
     grid1.Left = 0; 
     grid1.Top = 0; 
     grid1.Width = 400; 
     grid1.Height = 300; 
     myForm1.Controls.Add(grid1); 

     grid1.SelectedObject = new MyObject(); 

     PropertyGrid grid2 = new PropertyGrid(); 
     grid2.Left = 400; 
     grid2.Top = 0; 
     grid2.Width = 400; 
     grid2.Height = 300; 
     myForm1.Controls.Add(grid2); 

     object[] objects = new object[] { new MyObject(), new MyObject() }; 
     grid2.SelectedObjects = objects; 

     Application.Run(myForm1); 
    } 
} 


public class MyObject 
{ 
    [DisplayName("ZZZZ")] 
    public int AProperty 
    { 
     get; 
     set; 
    } 

    [DisplayName("BBBB")] 
    public int BProperty 
    { 
     get; 
     set; 
    } 

} 

Предыдущий код делает Form с дваPropertyGrids. Левая сетка содержит единственный объект в своем выборе, в то время как правая сетка содержит два объекта в своем выборе.

enter image description here

Все объекты одного и того же типа. Левая сетка сортируетproperties на основе DisplayNameAttribute, в то время как правильная сортировка основана на фактическом названии. В обоих случаях DisplayNameAttribute представлен как свойства называют в сетке:

Могу ли я силаPropertyGrid всегда использовать DisplayNameAttribute когда сортировки?

+0

Wow Microsoft ..... какой смысл отображать алфавитный рода ... если вы не сортируете отображаемое имя? Должен быть способ сделать это. – 00jt

ответ

2

Итак, я нашел ответ на свою проблему. Да, возможно, «force», или, может быть, более правильно «trick», PropertyGrid во все время уважения к DisplayName при сортировке. Суть проблемы заключалась в том, что «PropertyGrid» использует фактическое имя свойства при сортировке свойств нескольких выбранных объектов. Поэтому, чтобы получить желаемое поведение, мы должны заставить сету полагать, что DisplayName - это фактическое имя свойства. PropertyGrid использует PropertyDescriptors для обнаружения различных атрибутов свойств объектов. Нам просто нужен пользовательский PropertyDescriptor, который будет представлять DisplayName в качестве фактического названия свойства. Вот следующий код:

public class DisplayNameEnforcingDescriptor : PropertyDescriptor 
{ 
    private PropertyDescriptor _descriptor; 
    public DisplayNameEnforcingDescriptor(PropertyDescriptor descriptor) 
     : base(descriptor) 
    { 
     this._descriptor = descriptor; 
    } 

    public override string Name 
    { 
     get 
     { 
      return string.IsNullOrEmpty(DisplayName) ? base.Name : DisplayName; 
     } 
    } 

    public override bool CanResetValue(object component) 
    { 
     return _descriptor.CanResetValue(component); 
    } 

    public override Type ComponentType 
    { 
     get 
     { 
      return _descriptor.ComponentType; 
     } 
    } 

    public override object GetValue(object component) 
    { 
     return _descriptor.GetValue(component); 
    } 

    public override bool IsReadOnly 
    { 
     get 
     { 
      return _descriptor.IsReadOnly; 
     } 
    } 

    public override Type PropertyType 
    { 
     get 
     { 
      return _descriptor.PropertyType; 
     } 
    } 

    public override void ResetValue(object component) 
    { 
     _descriptor.ResetValue(component); 
    } 

    public override void SetValue(object component, object value) 
    { 
     _descriptor.SetValue(component, value); 
    } 

    public override bool ShouldSerializeValue(object component) 
    { 
     return _descriptor.ShouldSerializeValue(component); 
    } 
} 

предыдущий класс используется, чтобы обернуть существующий PropertyDescriptor и переопределить поведение свойства «Name».Свойство Name теперь вернет DisplayName (если не пустое или пустое) или имя фактического свойства. Все остальные функции делегируются обернутым PropertyDescriptor.

Итак, теперь у нас есть способ изменить представленное имя свойства, нам просто нужно, чтобы PropertyGrid использовал новый PropertyDescriptor. Для этого нам нужно настроить TypeDescriptor. Еще раз, вот следующий код:

public class DisplayNameEnforcingConverter : ExpandableObjectConverter 
{ 
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) 
    { 
     PropertyDescriptorCollection original = base.GetProperties(context, value, attributes); 
     List<DisplayNameEnforcingDescriptor> descriptorList = new List<DisplayNameEnforcingDescriptor>(); 
     foreach (PropertyDescriptor descriptor in original) 
      descriptorList.Add(new DisplayNameEnforcingDescriptor(descriptor)); 
     return new PropertyDescriptorCollection(descriptorList.ToArray()); 
    } 
} 

Этот класс наследуется от ExpandableObjectConverter использовать его существующее поведение и свести к минимуму нашей реализации. Нам нужно только переопределить метод GetProperties. Эти методы запрашивают базовый тип для получения соответствующего PropertyDescriptorCollection, а затем обертывают все элементы этой коллекции в нашем DisplayNameEnforcingDescriptor. Возвращается новый collection, связанный с нашими обернутыми элементами.

Теперь, если мы связываем MyObject класс с DisplayNameEnforcingConverter, сортировка всегда бывают основан на свойствах DisplayName

[TypeConverter(typeof(DisplayNameEnforcingConverter))] 
public class MyObject 
{ 
    [DisplayName("ZZZZ")] 
    public int AProperty 
    { 
     get; 
     set; 
    } 

    [DisplayName("BBBB")] 
    public int BProperty 
    { 
     get; 
     set; 
    } 
} 

enter image description here

0

Документы для PropertyGrid.PropertySortOrder состояний:

Чтобы сделать заказ сортировки, реализации ICustomTypeDescriptor на компоненте вернуть свойства в нужном порядке.

Я изменил свой класс для реализации ICustomTypeDescriptor и в то время как ICustomTypeDescriptor методы вызывалась и возвращалась свойства в порядке атрибутом DisplayName, PropertyGrid.SelectObjects до сих пор настаивают на сортировку по фактическому имени свойства:

public class MyObject : ICustomTypeDescriptor 
{ 
    [DisplayName("ZZZZ")] 
    public int AProperty 
    { 
     get; 
     set; 
    } 

    [DisplayName("BBBB")] 
    public int BProperty 
    { 
     get; 
     set; 
    } 

    public PropertyDescriptorCollection GetProperties() 
    { 
     // Creates a new collection and assign it the properties for button1. 
     var properties = TypeDescriptor.GetProperties(this) 
          .OfType<PropertyDescriptor>(); 
     var result = properties.OrderBy(x => x.DisplayName); 
     return new PropertyDescriptorCollection(result.ToArray()); 
    } 

    public PropertyDescriptorCollection GetProperties(Attribute[] attributes) 
    { 
     var properties = TypeDescriptor.GetProperties(this, attributes, true) 
          .OfType<PropertyDescriptor>(); 
     var result = properties.OrderBy(x => x.DisplayName); 
     return new PropertyDescriptorCollection(result.ToArray()); 
    } 

    public AttributeCollection GetAttributes() 
    { 
     return TypeDescriptor.GetAttributes(this, true); 
    } 

    public string GetClassName() 
    { 
     return TypeDescriptor.GetClassName(this, true); 
    } 

    public string GetComponentName() 
    { 
     return TypeDescriptor.GetComponentName(this, true); 
    } 

    public TypeConverter GetConverter() 
    { 
     return TypeDescriptor.GetConverter(this, true); 
    } 

    public EventDescriptor GetDefaultEvent() 
    { 
     return TypeDescriptor.GetDefaultEvent(this, true); 
    } 

    public PropertyDescriptor GetDefaultProperty() 
    { 
     return TypeDescriptor.GetDefaultProperty(this, true); 
    } 

    public object GetEditor(Type editorBaseType) 
    { 
     return TypeDescriptor.GetEditor(this, editorBaseType, true); 
    } 

    public EventDescriptorCollection GetEvents(Attribute[] attributes) 
    { 
     return TypeDescriptor.GetEvents(this, attributes, true); 
    } 

    public EventDescriptorCollection GetEvents() 
    { 
     return TypeDescriptor.GetEvents(this, true); 
    } 

    public object GetPropertyOwner(PropertyDescriptor pd) 
    { 
     return this; 
    } 
} 

Поскольку это не работает, кажется, что ответ на ваш вопрос: Нет, вы не можете заставить PropertyGrid сортировать по DisplayNameAttribute при выборе нескольких объектов.

Смежные вопросы