我正在尝试为一个拥有事件系统的游戏编写一个编辑器,其中包含事件的基类,然后是另一个实际执行所有操作的类。
因此,我有一个显示在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
}
答案 0 :(得分:1)
最后我找到了解决这个问题的方法:通过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);
}
}