Posted at

PropertyGridでList<T>を展開する


PropertyGridでListが配列みたいに展開されない件

上記、昔からあるあるで毎回調べてチャレンジしたり、あきらめたりしています。

昔からそんなもんだと割り切っていましたが、いい加減テンプレ化したいのでコピペ用のコードを記載します。


サンプルデータ

public class MyData

{
public int Id { get; set; }
public string[] Members { get; set;} = new string[] { "aaa", "bbb", "ccc" };
public List<string> MemberList { get { return Members.ToList();}}
}
void Form1_Load()
{
propertyGrid1.SelectedObject = new MyData(); //FormにPropertyGridが張り付けられているとする。
}

これを表示すると以下のように、MemberListがツリーに展開できません。

image.png

これを解決するため、まず準備として以下ListTypeConverterをコピペで作成しましょう。


ListTypeConverter(コピペ用)

public class ListTypeConverter : TypeConverter

{
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType != typeof(string))
return base.ConvertTo(context, culture, value, destinationType);
string type = value.GetType().GenericTypeArguments[0].Name;
IList members = value as IList;
if (members == null)
return "-";
return $"List<{type}>[{members.Count}]";//Listのルートのところをどう出すか
}

public override bool GetPropertiesSupported(ITypeDescriptorContext context) { return true; }

public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
List<PropertyDescriptor> list = new List<PropertyDescriptor>();
IEnumerable members = value as IEnumerable;
if (members != null)
{
foreach (var member in members)
{
list.Add(new MemberDescriptor(member, list.Count));
}
}
return new PropertyDescriptorCollection(list.ToArray());
}

private class MemberDescriptor : SimplePropertyDescriptor
{
public object Member { get; private set; }
public MemberDescriptor(object member, int index)
: base(member.GetType(), $"[{index}]", typeof(string))//展開時[0]の所をどう出すか
{
Member = member;
}
public override object GetValue(object component)
{
return Member;
}
public override void SetValue(object component, object value)
{
Member = value;
}
}
}


これをListなプロパティの前にTypeConverter属性として付加します。


サンプルデータ

public class MyData

{
public int Id { get; set; }
[TypeConverter(typeof(ListTypeConverter))]// *追加*
public string[] Members { get; set;} = new string[] { "aaa", "bbb", "ccc" };
public List<string> MemberList { get { return Members.ToList();}}
}

実行結果は下記です。ついでに配列のメンバ数もルートに出しました。

image.png


参考にしたサイト

StackOverflow - Properly display list of custom objects in Windows Forms' Property Grid


関連記事

C#でコスパの良いデータダンプ方法(メインページ)