2009-12-10 26 views
5

私は任意のオブジェクトのプロパティを編集できるようにするGUIアプリケーションを作成しています(そのタイプは実行時にのみ認識されます)。PropertyGridとオブジェクトの動的タイプ

私はこの機能を有効にするためにPropertyGridコントロールを使用することに決めました。私は編集する必要があるオブジェクトのインスタンスを取得する場合、私はそれのためのラッパーを作成し、選択したオブジェクトとして設定し

[TypeConverter(typeof(ExpandableObjectConverter))] 
[DefaultPropertyAttribute("Value")] 
public class Wrapper 
{ 
    public Wrapper(object val) 
    { 
     m_Value = val; 
    } 

    private object m_Value; 

    [NotifyParentPropertyAttribute(true)] 
    [TypeConverter(typeof(ExpandableObjectConverter))] 
    public object Value 
    { 
     get { return m_Value; } 
     set { m_Value = value; } 
    } 
} 

Wrapper wrap = new Wrapper(obj); 
propertyGrid.SelectedObject = wrap; 

しかし、私 は、私は、次のクラスを作成しましたobjの型がいくつかのカスタム型(つまり、自分で定義したクラス、または複合型で構築したクラス)であっても、objがプリミティブでないときにのみ、上記のように動作します。

[TypeConverter(typeof(ExpandableObjectConverter))] 
public class SomeClass 
{ 
    public SomeClass() 
    { 
     a = 1; 
     b = 2; 
    } 

    public SomeClass(int a, int b) 
    { 
     this.a = a; 
     this.b = b; 
    } 

    private int a; 

    [NotifyParentPropertyAttribute(true)] 
    public int A 
    { 
     get { return a; } 
     set { a = value; } 
    } 

    private int b; 

    [NotifyParentPropertyAttribute(true)] 
    public int B 
    { 
     get { return b; } 
     set { b = value; } 
    } 
} 

をと実行します:たとえば

は、私が定義した場合

そして、すべての作品が膨らみます。私は次のことを行う一方、:

int num = 1; 
Wrapper wrap = new Wrapper(num); 
propertyGrid.SelectedObject = wrap; 

それから私は、グリッド内の「1」の値を見ることができます(そしてそれがグレイスケールではないです)が、私は値を編集することはできません。 Wrapperの "Value"プロパティの型をintに変更してTypeConverter属性を削除すると、それが機能することに気付きました。 他のプリミティブ型と文字列で同じ動作が発生します。

何が問題ですか?

ありがとうございます!

答えて

5

ExpandableObjectConverterをValueプロパティに設定した場合、CanConvertFromがfalseを返すため、これは編集できません。これは正常です。タイプコンバーターを削除すると、PropertyGridはジェネリックTypeConverterを使用し、同じケースに入ります。したがって回避策は、正しいTypeConverterへのラッパーとして機能するよりスマートなTypeConverterを接続することです。

public class MySmartExpandableObjectConverter : ExpandableObjectConverter 
{ 
    TypeConverter actualConverter = null; 

    private void InitConverter(ITypeDescriptorContext context) 
    { 
     if (actualConverter == null) 
     { 
      TypeConverter parentConverter = TypeDescriptor.GetConverter(context.Instance); 
      PropertyDescriptorCollection coll = parentConverter.GetProperties(context.Instance); 
      PropertyDescriptor pd = coll[context.PropertyDescriptor.Name]; 

      if (pd.PropertyType == typeof(object)) 
       actualConverter = TypeDescriptor.GetConverter(pd.GetValue(context.Instance)); 
      else 
       actualConverter = this; 
     } 
    } 

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
    { 
     InitConverter(context); 

     return actualConverter.CanConvertFrom(context, sourceType); 
    } 

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
    { 
     InitConverter(context); // I guess it is not needed here 

     return actualConverter.ConvertFrom(context, culture, value); 
    } 
} 

は、あなたが何かを微調整する必要がある場合、私に教えてください:ここでは汚れ一つは(私はちょうどConvertFrom部品を実装するので、必要に応じて、あなたはそれを完了します、ではない多くの時間を持っていた)です。

ニコラス

+0

ありがとう、それはトリックでした! :) – Marina

+0

なぜこの行 'parentConverter.GetProperties(context.Instance);'はnullを返しますか? –

0

プロパティ "値"から "TypeConverter"を削除すると、プロパティグリッドはプロパティに値の型の "TypConverter"を読み込みます。

+1

私は、残念ながら – Marina

+0

(それはobjが原始的でない場合でも、これを行います)私はこれを行うときに、プロパティグリッドが正しくプロパティの値を表示しますが、グレースケールや編集が無効になっている、それを試してみましたMS PropertyGridはあなたのValueプロパティにコンバーターを設定しないでください。 intの場合、Int32ConverterではなくTypeConverterを返します。私はSPGでこの事件を処理しなければならなかったので、私はそれを知っています。回避策のために私の答えを見てください。 –

+0

ええ、あなたは正しいです。今まで私は信念を持って住んでいました。そのプロパティグリッドはとてもスマートです。おかげで – TcKs

関連する問題