8

に 1 つのクラスの複数のインスタンスを表示したいPropertyGrid。クラスは次のようになります。

public class Parameter
{
    [Description("the name")]
    public string Name { get; set; }

    [Description("the value"), ReadOnly(true)]
    public string Value { get; set; }

    [Description("the description")]
    public string Description { get; set; }
}

にそのクラスの多くのインスタンスがありますTreeView。でそれらのいずれかを選択するとTreeView、プロパティがPropertyGrid期待どおりに表示されます。ここまでは順調ですが、この動作を次のようにカスタマイズしたいと思います。

単一のインスタンスごとに、ユーザーが特定のプロパティを変更できないようにしたいと考えています。クラス内で設定することによりReadOnly(true)(上記の例でわかるように)、すべてのValueプロパティがクラスレベルで無効になります。

いくつかの調査の後、実行時に特定のプロパティを有効/無効にする機会を与える次の解決策を見つけました。

PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this)["Value"];

ReadOnlyAttribute attr = 
        (ReadOnlyAttribute)descriptor.Attributes[typeof(ReadOnlyAttribute)];

FieldInfo isReadOnly = attr.GetType().GetField(
        "isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);

isReadOnly.SetValue(attr, false);

このアプローチは問題なく機能しますが、残念ながらクラスレベルでのみ機能します。これは、 を に設定すると、すべてValueの-objects のプロパティが書き込み可能になることを意味します。しかし、私はこれをその1つの特定のオブジェクト(したがってobject-level)でのみ必要とします。読み取り/書き込みプロパティと読み取り専用プロパティ用に個別のクラスを作成したくありません。isReadOnlyfalseParameterValue

私はアイデアが不足しているので、あなたの助けは大歓迎です:)

前もって感謝します!

編集:読み取り専用プロパティをグレー表示にする必要があるため、ユーザーは編集が許可されていない、または編集できないことがわかります。

4

2 に答える 2

5

編集:リンクされた記事は削除されました(一時的なものだといいのですが)。How to add property-level Attribute to the TypeDescriptor at runtime? への回答で実行可能な代替手段を見つけることができますか? . 基本的に、そのプロパティReadOnlyAttributeの を介して(実行時に) 追加する必要があります。TypeDescriptor


CodeProject に関するこの古くて素晴らしい記事を 見くださいPropertyGrid

基本的に、プロパティの属性を取得するために使用されるクラスまたはデリゲートを提供します。属性を取得したいオブジェクトのインスタンスを渡して呼び出されるため、ReadOnlyAttributeオブジェクトごとに を返す (または返さない) ことができます。手短に: プロパティに a を適用し、独自のプロバイダーを作成し、(クラスではなく) オブジェクト自体に基づいてコレクションPropertyAttributesProviderAttributeの属性を置き換えます。PropertyAttributes

于 2012-05-07T12:49:15.880 に答える
1

オブジェクトをカスタム型記述子でラップすることはできますが、新しい型記述子派生クラスを作成する必要があるため、それはやり過ぎだと思います。

したがって、最も簡単な解決策は、次のようなフラグを設定することです。

public class Parameter 
{ 
    private string thevalue;

    [Browsable(false)]
    public bool CanEditValue { get; set; }

    [Description("the name")] 
    public string Name { get; set; } 

    [Description("the description")] 
    public string Description { get; set; }

    [Description("the value"), ReadOnly(true)] 
    public string Value { 
        get { return this.thevalue; }
        set { if (this.CanEditValue) this.thevalue = value; } 
    }
}
于 2012-05-07T12:47:22.177 に答える