C# 如何显示;“价值”;PropertyGrid中对象的属性

C# 如何显示;“价值”;PropertyGrid中对象的属性,c#,winforms,propertygrid,C#,Winforms,Propertygrid,我试图为一个有事件系统的游戏制作一个编辑器,为事件创建一个基类,然后为每种类型创建另一个类,它们实际上完成了所有的工作 因此,我有一个显示在PropertyGrid中的BaseEvent列表,作为一个列表,集合编辑器打开。我准备了一个TypeConverter,所以我有一个包含所有派生类的下拉列表,显示在“Value”属性中 一切正常,派生类的属性显示为“Value”的子级,但只要我想显示BaseEvent的属性,“Value”属性就会消失,子级出现在根级,因此我无法更改事件的类型 是否有办法使

我试图为一个有事件系统的游戏制作一个编辑器,为事件创建一个基类,然后为每种类型创建另一个类,它们实际上完成了所有的工作

因此,我有一个显示在PropertyGrid中的BaseEvent列表,作为一个列表,集合编辑器打开。我准备了一个TypeConverter,所以我有一个包含所有派生类的下拉列表,显示在“Value”属性中

一切正常,派生类的属性显示为“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
}
//这允许获取派生类的下拉列表
公共类EventTypeConverter:ExpandableObjectConverter
{
公共覆盖标准值集合GetStandardValues(ITypeDescriptor上下文)
{
返回新的StandardValuesCollection(GetAvailableType());
}
/*
...
*/
}
[TypeConverter(typeof(EventTypeConverter))]
公共抽象类BaseEvent
{
public bool BaseProperty;//{get;set;}如果我将其设置为属性,“Value”将消失
}
公共类SomeEvent:BaseEvent
{
公共bool SomeOtherProperty{get;set;}
}
//在PropertyGrid中选择的对象属于此类型
公共类事件管理器
{
公共列表事件{get;set;}//打开集合编辑器的列表
}

最后我找到了一种解决方法:通过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);
    }
}

最后,我找到了一种解决方法:通过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);
    }
}

我发现了一种解决方法,它包括在所有子类(如“public new bool BaseProperty{get{return base.BaseProperty;}}”)中重写BaseProperty,尽管它不是很优雅……我发现了一种解决方法,它包括在所有子类(如“public new bool BaseProperty{get”)中重写BaseProperty{return base.BaseProperty;}}“虽然不是很优雅。。。