Как показать свойство «Значение» объекта в PropertyGrid - PullRequest
1 голос
/ 11 марта 2012

Я пытаюсь создать редактор для игры, в котором есть система событий, с базовым классом для событий, а затем еще один класс для каждого вида, который фактически выполняет все функции.

Итак, у меня есть список BaseEvent, который отображается в PropertyGrid, и в виде списка открывается редактор коллекции. Я подготовил TypeConverter, поэтому у меня есть раскрывающийся список со всеми производными классами, который отображается в свойстве «Значение».

Все в порядке, свойства из производных классов отображаются как дочерние элементы «Value», но как только я хочу показать свойство из BaseEvent, свойство «Value» исчезает, и дочерние элементы появляются в корне, поэтому я невозможно изменить тип события.

Есть ли способ сделать так, чтобы свойство "Value" отображалось одновременно со свойствами BaseEvent?

//This allows to get a dropdown for the derived classes
public class EventTypeConverter : ExpandableObjectConverter
{
    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        return new StandardValuesCollection(GetAvailableTypes());
    }

    /*
    ...
    */
}

[TypeConverter(typeof(EventTypeConverter))]
public abstract class BaseEvent
{
    public bool BaseProperty; //{ get; set; } If I set this as a property, "Value" disappears
}

public class SomeEvent : BaseEvent
{
    public bool SomeOtherProperty { get; set; }
}

//The object selected in the PropertyGrid is of this type
public class EventManager
{
    public List<BaseEvent> Events { get; set; } //The list that opens the collection editor
}

1 Ответ

1 голос
/ 06 апреля 2012

Наконец, я нашел способ решить эту проблему: с помощью метода GetProperties и пользовательского PropertyDescriptor:

public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
    //Get the base collection of properties
    PropertyDescriptorCollection basePdc = base.GetProperties(context, value, attributes);

    //Create a modifiable copy
    PropertyDescriptorCollection pdc = new PropertyDesctiptorCollection(null);
    foreach (PropertyDescriptor descriptor in basePdc)
        pdc.Add(descriptor);

    //Probably redundant check to see if the value is of a correct type
    if (value is BaseEvent)
        pdc.Add(new FieldDescriptor(typeof(BaseEvent), "BaseProperty"));
    return pdc;
}

public class FieldDescriptor : SimplePropertyDescriptor
{
    //Saves the information of the field we add
    FieldInfo field;

    public FieldDescriptor(Type componentType, string propertyName)
        : base(componentType, propertyName, componentType.GetField(propertyName, BindingFlags.Instance | BindingFlags.NonPublic).FieldType)
    {
        field = componentType.GetField(propertyName, BindingFlags.Instance | BindingFlags.NonPublic);
    }

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

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