Есть ли способ отобразить статические свойства в PropertyGrid?

У меня есть PropertyGrid, который отображает все свойства экземпляра для объекта. Есть ли способ также отображать статические свойства класса, к которому принадлежит объект, либо в том же, либо в отдельном PropertyGrid? В качестве альтернативы, есть ли другой элемент управления Forms, который позволил бы мне это сделать?

Исследования с использованием Класс CustomTypeDescriptor для предоставления индивидуального представления объекта. Есть много примеров базовой процедуры.

TnTinMn 30.05.2019 05:01
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
357
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Дескрипторы типов отвечают за предоставление списка свойств для отображения в 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);

Примечание: Самым простым обходным решением для вас было бы использование свойств экземпляра, которые являются обертками статических свойств.
Reza Aghaei 30.05.2019 06:02

Другие вопросы по теме