Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 修改PropertyGrid中的结构属性_.net_Winforms_Propertygrid - Fatal编程技术网

.net 修改PropertyGrid中的结构属性

.net 修改PropertyGrid中的结构属性,.net,winforms,propertygrid,.net,Winforms,Propertygrid,为什么SomeClass.ClassField.StructField属性在propertyGrid中没有更改? 似乎,propertyGrid在SomeStruct实例更改后,不会调用SomeClass.ClassField.set。但是相同的代码可以很好地处理点,而不是SomeStruct [TypeConverter(typeof(ExpandableObjectConverter))] public struct SomeStruct { private int structFi

为什么
SomeClass.ClassField.StructField
属性在
propertyGrid
中没有更改? 似乎,
propertyGrid
SomeStruct
实例更改后,不会调用
SomeClass.ClassField.set
。但是相同的代码可以很好地处理
,而不是
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;

您需要一个特殊的类型转换器来覆盖,因为否则,按值复制/装箱魔术会在场景后面发生,以属性网格处理所有这些

这是一个适用于大多数值类型的方法。您这样声明:

[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;
    }
}
[TypeConverter(typeof(valuetypeconverter))]
公共结构SomeStruct
{
公共int结构域{get;set;}
}
公共类ValueTypeConverter:ExpandableObjectConverter,其中T:struct
{
公共覆盖布尔GetCreateInstanceSupported(ITypeDescriptorContext上下文)
{
返回true;
}
公共重写对象CreateInstance(ITypeDescriptorContext上下文,IDictionary属性值)
{
if(PropertyValue==null)
抛出新ArgumentNullException(“PropertyValue”);
T ret=默认值(T);
装箱对象=ret;
foreach(字典在PropertyValue中输入条目)
{
PropertyInfo pi=ret.GetType().GetProperty(entry.Key.ToString());
if(pi!=null&&pi.CanWrite)
{
pi.SetValue(装箱,Convert.ChangeType(entry.Value,pi.PropertyType),null);
}
}
返回(T)装箱;
}
}

请注意,它不支持纯字段结构,只支持带有属性的结构,但ExpandableObjectConverter也不支持这些结构,它需要更多的代码来完成。我调整了Simon Mourier的答案,以避免ValueTypeConverter成为泛型:

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;
    }
}

在我的例子中,泛型参数在编译时是未知的(插件的选项结构)。您可以使用
context.PropertyDescriptor.GetValue(context.Instance)获取当前值的副本

  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;
  }

结构应该是不可变的。这个是可变的。与点/矩形等相同。好的点(额外字符)请注意“ExpandableObjectConverter”中的“Object”一词。您将编辑结构的装箱副本,它不会传播回。以PointConverter的实现为例。@Hans Passant,非常感谢,它可以工作。