修改PropertyGrid中的结构属性

时间:2013-04-01 16:03:33

标签: .net winforms propertygrid

为什么SomeClass.ClassField.StructField属性在propertyGrid中没有变化? 似乎propertyGridSomeClass.ClassField.set实例更改后没有调用SomeStruct。但是相同的代码适用于Point而不是SomeStruct

[TypeConverter(typeof(ExpandableObjectConverter))]
public struct SomeStruct
{
    private int structField;

    public int StructField
    {
        get
        {
            return structField;
        }
        set
        {
            structField = value;
        }
    }

    public override string ToString()
    {
        return "StructField: " + StructField;
    }
}

[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class SomeClass
{
    public SomeStruct ClassField
    {
        get;
        set;
    }
}

...

var someClass = new SomeClass
{
    ClassField = new SomeStruct
    {
        StructField = 42
    }
};
propertyGrid.SelectedObject = someClass;

3 个答案:

答案 0 :(得分:7)

你需要一个特殊的TypeConverter来覆盖TypeConverter.GetCreateInstanceSupported,因为否则按照值/按重量计算魔法会以属性网格处理所有这些的方式发生在场景后面。

这是适用于大多数值类型的一个。你声明它是这样的:

[TypeConverter(typeof(ValueTypeTypeConverter<SomeStruct>))]
public struct SomeStruct
{
    public int StructField { get; set; }
}


public class ValueTypeTypeConverter<T> : ExpandableObjectConverter where T : struct
{
    public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
    {
        if (propertyValues == null)
            throw new ArgumentNullException("propertyValues");

        T ret = default(T);
        object boxed = ret;
        foreach (DictionaryEntry entry in propertyValues)
        {
            PropertyInfo pi = ret.GetType().GetProperty(entry.Key.ToString());
            if (pi != null && pi.CanWrite)
            {
                pi.SetValue(boxed, Convert.ChangeType(entry.Value, pi.PropertyType), null);
            }
        }
        return (T)boxed;
    }
}

请注意,它不支持纯字段结构,只支持具有属性的结构,但ExpandableObjectConverter也不支持这些结构,它需要更多代码才能执行此操作。

答案 1 :(得分:3)

我调整了Simon Mourier的答案,以避免ValueTypeTypeConverter成为泛型:

public class ValueTypeTypeConverter : System.ComponentModel.ExpandableObjectConverter
{
    public override bool GetCreateInstanceSupported(System.ComponentModel.ITypeDescriptorContext context)
    {
        return true;
    }

    public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext context, System.Collections.IDictionary propertyValues)
    {
        if (propertyValues == null)
            throw new ArgumentNullException("propertyValues");

        object boxed = Activator.CreateInstance(context.PropertyDescriptor.PropertyType);
        foreach (System.Collections.DictionaryEntry entry in propertyValues)
        {
            System.Reflection.PropertyInfo pi = context.PropertyDescriptor.PropertyType.GetProperty(entry.Key.ToString());
            if ((pi != null) && (pi.CanWrite))
            {
                pi.SetValue(boxed, Convert.ChangeType(entry.Value, pi.PropertyType), null);
            }
        }
        return boxed;
    }
}

答案 2 :(得分:0)

在我的例子中,泛型参数在编译时是不可知的(插件的选项结构)。您可以使用 public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues) { if (propertyValues == null) throw new ArgumentNullException("propertyValues"); object boxed = context.PropertyDescriptor.GetValue(context.Instance); foreach (DictionaryEntry entry in propertyValues) { PropertyInfo pi = boxed.GetType().GetProperty(entry.Key.ToString()); if (pi != null && pi.CanWrite) pi.SetValue(boxed, Convert.ChangeType(entry.Value, pi.PropertyType), null); } return boxed; } 获取当前值的副本:

$app->response->redirect($app->urlFor('games.markets', array('game' => $id)));