У меня есть PropertyGrid
, который отображает все свойства экземпляра для объекта. Есть ли способ также отображать статические свойства класса, к которому принадлежит объект, либо в том же, либо в отдельном PropertyGrid
? В качестве альтернативы, есть ли другой элемент управления Forms, который позволил бы мне это сделать?
Дескрипторы типов отвечают за предоставление списка свойств для отображения в PropertyGrid
.
Чтобы настроить список свойств, вам необходимо указать собственное описание типа для вашего класса/объекта, используя один из следующих вариантов:
ICustomTypeDescriptor
CustomTypeDescriptor
TypeDescriptionProvider
, зарегистрировав его для своего класса или экземпляра объекта.CustomTypeDescriptor
, чтобы использовать его для PropertyGrid
.Пример
В этом примере я реализовал последний вариант. Я предполагаю, что вы собираетесь оставить основной класс без изменений, и только для того, чтобы показать в PropertyGrid
, я создал пользовательский объект-оболочку, который предоставляет список свойств для сетки свойств, включая статические свойства.
Допустим, у вас есть такой класс:
public class MyClass
{
public string InstanceProperty { get; set; }
public static string StaticProperty { get; set; } = "Test";
}
И вы хотите показать его свойства в PropertyGrid
.
Тогда обычно первое, что вам нужно, это новый дескриптор свойства:
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
public class StaticPropertyDescriptor : PropertyDescriptor
{
PropertyInfo p;
Type owenrType;
public StaticPropertyDescriptor(PropertyInfo pi, Type owenrType)
: base(pi.Name,
pi.GetCustomAttributes().Cast<Attribute>().ToArray())
{
p = pi;
this.owenrType = owenrType;
}
public override bool CanResetValue(object c) => false;
public override object GetValue(object c) => p.GetValue(null);
public override void ResetValue(object c) { }
public override void SetValue(object c, object v) => p.SetValue(null, v);
public override bool ShouldSerializeValue(object c) => false;
public override Type ComponentType { get { return owenrType; } }
public override bool IsReadOnly { get { return !p.CanWrite; } }
public override Type PropertyType { get { return p.PropertyType; } }
}
Тогда вы можете использовать любой из вариантов, которые я упомянул выше. Например, здесь я создал дескриптор типа оболочки, чтобы не касаться исходного класса:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
public class CustomObjectWrapper : CustomTypeDescriptor
{
public object WrappedObject { get; private set; }
private IEnumerable<PropertyDescriptor> staticProperties;
public CustomObjectWrapper(object o)
: base(TypeDescriptor.GetProvider(o).GetTypeDescriptor(o))
{
WrappedObject = o;
}
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
var instanceProperties = base.GetProperties(attributes)
.Cast<PropertyDescriptor>();
staticProperties = WrappedObject.GetType()
.GetProperties(BindingFlags.Static | BindingFlags.Public)
.Select(p => new StaticPropertyDescriptor(p, WrappedObject.GetType()));
return new PropertyDescriptorCollection(
instanceProperties.Union(staticProperties).ToArray());
}
}
И использование довольно простое:
var myClass = new MyClass();
propertyGrid1.SelectedObject = new CustomObjectWrapper (myClass);
Исследования с использованием Класс CustomTypeDescriptor для предоставления индивидуального представления объекта. Есть много примеров базовой процедуры.