5

任意のオブジェクトのプロパティの編集を有効にする必要があるGUIアプリケーションを作成しています(それらのタイプは実行時にのみ認識されます)。

この機能を有効にするために、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; }
    }
}

そして、やります:

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

その後、すべてが膨らみます。一方、私が以下を実行する場合:

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

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

何が問題ですか?

前もって感謝します!

4

2 に答える 2

5

ExpandableObjectConverterをValueプロパティに設定すると、編集できなくなります。CanConvertFromがfalseを返すため、これは正常です。タイプコンバーターを削除すると、PropertyGridは汎用のTypeConverterを使用し、同じケースになります。したがって、回避策は、ラッパーとして機能するよりスマートなTypeConverterを正しいTypeConverterに接続することです。これは汚いものです(私はあまり時間がありませんでした。ConvertFrom部分を実装したばかりなので、必要に応じて完了します):

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

何かを微調整する必要がある場合はお知らせください。

ニコラス

于 2009-12-11T01:53:47.647 に答える
0

プロパティ「Value」から「TypeConverter」を削除すると、propertygridはプロパティにあるvalueのtypeoから「TypConverter」を読み取ります。

于 2009-12-10T23:35:02.107 に答える