2013-04-01 78 views
6

爲什麼SomeClass.ClassField.StructField屬性在propertyGrid中未更改? 看來,propertyGrid不會調用SomeClass.ClassField.setSomeStruct實例已被更改。但是相同的代碼與Point而不是SomeStruct的效果很好。修改PropertyGrid中的結構屬性

[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; 
+0

結構應該是一成不變的 – Filip

+0

這一個是可變的。與點/矩形等相同。 – nitrocaster

+0

好點(多餘字符) – Filip

回答

7

你需要重寫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不支持這些要麼,它需要更多的代碼來做到這一點。

3

我調整西蒙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; 
    } 
} 
0

在我的情況下,一般的說法是不是在編譯時(選項結構的插件)聞名。你可以使用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; 
    }