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がツリーに展開できません。
これを解決するため、まず準備として以下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();}}
}
実行結果は下記です。ついでに配列のメンバ数もルートに出しました。
参考にしたサイト
StackOverflow - Properly display list of custom objects in Windows Forms' Property Grid