web-dev-qa-db-ja.com

WinForms PropertyGridを使用して文字列のリストを編集するにはどうすればよいですか?

私のアプリケーションには、ユーザーが設定を変更できるようにするプロパティグリッドがあります。これは文字列やその他の値のプロパティでは問題なく機能しますが、今必要なのはユーザーが編集できる文字列のリストです。

問題は、コードにMyPropertyGrid.SelectedObject = new { Test = new List<string>() };があり、ユーザーがTestプロパティを編集しようとしたときに、[追加]ボタンをクリックすると、次のエラーが発生することです。

 Constructor on type 'System.String' not found

文字列は不変であるため、これは理にかなっています。ただし、プロパティグリッドに複数の文字列(または文字列のようなデータ)を格納する方法が必要です。

誰かが私がこれを達成する方法について何かアイデアがありますか?

21
KallDrexx

はい、できます StringCollectionEditorをエディターとして、文字列のリストにSystem.ComponentModel.Editor属性を指定してください 。これをコンパイルするには、System.Design.Dllへの参照をプロジェクトに追加する必要があります。

たとえば、オブジェクトが次のようになっているとします。

[DefaultProperty("Name")]
public class CustomObject
{
    [Description("Name of the thing")]
    public String Name { get; set; }

    [Description("Whether activated or not")]
    public bool Activated { get; set; }

    [Description("Rank of the thing")]
    public int Rank { get; set; }

    [Description("whether to persist the settings...")]
    public bool Ephemeral { get; set; }

    [Description("extra free-form attributes on this thing.")]
    [Editor(@"System.Windows.Forms.Design.StringCollectionEditor," +
        "System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
       typeof(System.Drawing.Design.UITypeEditor))]
    [TypeConverter(typeof(CsvConverter))]
    public List<String> ExtraStuff
    {
        get
        {
            if (_attributes == null)
                _attributes = new List<String>();
            return _attributes;
        }
    }
    private List<String> _attributes;
}

そのためのプロパティグリッドは次のようになります。

enter image description here

...をクリックすると、次のようになります。

enter image description here

組み込みのコレクションエディタが気に入らない場合は、 独自のカスタムコレクションエディタを実装できます

私の例は、TypeConverter属性の使用法を示しています。あなたがそれをしない場合、リストは「(コレクション)」として小道具グリッドに表示されます。 TypeConverter インテリジェントなものとして表示する 。たとえば、コレクションの短い文字列表現をプロパティグリッドに表示するには、次のようにします。

enter image description here

... TypeConverterは次のようになります:

public class CsvConverter : TypeConverter
{
    // Overrides the ConvertTo method of TypeConverter.
    public override object ConvertTo(ITypeDescriptorContext context,
       CultureInfo culture, object value, Type destinationType)
    {
        List<String> v = value as List<String>;
        if (destinationType == typeof(string))
        {
            return String.Join(",", v.ToArray()); 
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

コレクションエディタはそのプロパティを設定せず、プロパティにエントリを追加または削除するだけなので、List<String>にセッターは必要ありません。だから、ゲッターを提供するだけです。

47
Cheeso

文字列コンテナが必要な場合は、_BindingList<string>_の代わりに_list<string>_を使用してください。

エディターは自動的に作成されます。

また、_List<T>_との「キャスト」も簡単です。 ListからBindingListまでは、bList = BindingList(orignalList)コンストラクターを使用するだけです(読み取り専用エラーが発生した場合は、リストを1つずつ挿入してください)。リストを取得するには、.ToList()拡張メソッドを使用できます。

7
Guy L

プロパティ宣言には、1つの重要な属性がありません:[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

それがないと、デザイナーはコレクションデータをシリアル化しません。

3
Janusz Skalski