ListBoxで内部の値とは別に表示する値を自由自在に変更する

2015/04/14
別の方法を見つけたのでエントリを書いた
ListBox(ComboBox)で内部の値とは別に表示する値を自由自在に変更する Part2 - posnum’s blog

最も単純な方法としては、 ListBox に DataSource を設定し、DisplayMember プロパティに表示したいメンバを設定する。

例えば、以下のクラスがあったとする。

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

以下のように ListBox の DataSource プロパティに設定し、 DisplayMember に "Name" を指定してやれば良い。

var persons = new Person[]
{
    new Person { Name = "Smith", Age = 20 },
    new Person { Name = "John", Age = 35 },
    new Person { Name = "Mike", Age = 15 }
};
listBox1.DataSource = persons;
listBox1.DisplayMember = "Name";

f:id:posnum:20141108113827j:plain

ただ、この方法だと "Name" か "Age" をそのまま表示することしかできない。 Smith, 20 のように表示したいこともある。 (この例だと ListBox を使うのは適切ではないかもしれないが)

方法は大きく2つあり、ひとつは Person クラスで ToString() メソッドをオーバーライドしてやれば良い。

ListBox などは、DisplayMember を指定していない場合、 設定されているクラスの ToString() メソッドを呼び出して表示に利用している。

ただ、この方法は場合によってはおおげさだ。 表示のためだけにクラスをいじりたくない場合も多いだろう。

オススメなのがもうひとつの方法。

Formatイベントを利用する方法である。 これを用いることで実質なんでも表示できるようになる。

VisualStudioでプロパティウィンドウから設定することができる。

f:id:posnum:20141108114603j:plain

e.ListItem にリストの項目のオブジェクトが入っており、 e.Value に表示したい内容を設定できる。 ここでは string.Format を使ってみた。

private void Form1_Load(object sender, EventArgs e)
{
    var persons = new Person[]
    {
        new Person { Name = "Smith", Age = 20 },
        new Person { Name = "John", Age = 35 },
        new Person { Name = "Mike", Age = 15 }
    };

    listBox1.DataSource = persons;
}

private void listBox1_Format(object sender, ListControlConvertEventArgs e)
{
    var person = (Person)e.ListItem;
    e.Value = string.Format(@"{0}, {1}", person.Name, person.Age);
}

f:id:posnum:20141108114801j:plain

この方法が素晴らしいのは、表示するためのクラスを作成したり、 元のクラスをいじったりしないことである。

非常に便利。

参考: DisplayMemberとValueMemberプロパティについて: .NET Tips: C#, VB.NET