DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

DisplayMemberとValueMemberプロパティについて

DisplayMemberプロパティ

ListBoxやComboBoxのDataSourceプロパティには、文字列(String型)以外のオブジェクトのコレクションを指定することができます(同様に、ItemsプロパティのAddメソッド等を使って、文字列以外のオブジェクトを追加することもできます)。このときにリストに表示される項目の文字列は、そのオブジェクトのToStringメソッドが返す値(ただし、nullの時は空の文字列)となります。

もしToStringではなく、あるプロパティが返す値を表示したいのであれば、そのプロパティの名前をDisplayMemberプロパティに指定します。

例えば、Encoding.GetEncodingsが返すエンコーディングの配列をListBoxに追加し、項目にエンコーディングの表示名(Encoding.DisplayNameプロパティ)を表示させるには、次のようにします。

VB.NET
コードを隠すコードを選択
'DisplayNameプロパティを項目の表示に利用する
ListBox1.DisplayMember = "DisplayName"
'エンコーディングの配列をListBox1のデータソースに設定する
ListBox1.DataSource = System.Text.Encoding.GetEncodings()
C#
コードを隠すコードを選択
//DisplayNameプロパティを項目の表示に利用する
ListBox1.DisplayMember = "DisplayName";
//エンコーディングの配列をListBox1のデータソースに設定する
ListBox1.DataSource = System.Text.Encoding.GetEncodings();

DisplayName

補足:DisplayMemberプロパティはリストに項目を追加する前(DataSourceプロパティに格納する前)に設定すべきです。DataSourceプロパティ格納後にDisplayMemberプロパティを設定すると、リストに項目を表示しなおすための時間がかかるため、遅くなります。

ValueMemberプロパティ

ValueMemberプロパティは、SelectedValueプロパティで取得、設定できるようにする値を指定するためのものと考えてよいでしょう。SelectedValueプロパティで、現在選択されている項目のValueMemberプロパティで指定されたプロパティの値を取得できます。また、指定された値をValueMemberプロパティで指定されたプロパティにもつ項目を探して選択するために、SelectedValueプロパティを使うこともできます。特に後者の使い方は重宝します。

ただしDataSourceプロパティを設定せずに、ItemsプロパティのAddメソッドによりオブジェクトを追加したときは、ValueMemberプロパティにかかわらず、SelectedValueプロパティは常にnull(VB.NETでは、Nothing)を返すようです。

補足:DisplayMemberが指定されていないときにValueMemberを設定すると、DisplayMemberも同じ値になります。
補足:ValueMemberが指定されていないとき、SelectedValueはそのオブジェクトのToStringメソッドが返す値になるとMSDNにはありますが、私が試した限りではそうはならず、SelectedItemプロパティと同じ値を返すようでした。

以下の例では、先の例に追加して、ValueMemberプロパティに"CodePage"を指定しています。このようにすると、「ListBox1.SelectedValue」で現在選択されているエンコーディングのコードページを取得したり、コードページでエンコーディングを選択したりすることができます。

VB.NET
コードを隠すコードを選択
'DisplayNameプロパティを項目の表示に利用する
ListBox1.DisplayMember = "DisplayName"
'CodePageプロパティをSelectedValueで取得、設定できる値に利用する
ListBox1.ValueMember = "CodePage"
'エンコーディングの配列をListBox1のデータソースに設定する
ListBox1.DataSource = System.Text.Encoding.GetEncodings()

'コードページが932の項目を選択する
ListBox1.SelectedValue = 932
C#
コードを隠すコードを選択
//DisplayNameプロパティを項目の表示に利用する
ListBox1.DisplayMember = "DisplayName";
//CodePageプロパティをSelectedValueで取得、設定できる値に利用する
ListBox1.ValueMember = "CodePage";
//エンコーディングの配列をListBox1のデータソースに設定する
ListBox1.DataSource = System.Text.Encoding.GetEncodings();

//コードページが932の項目を選択する
ListBox1.SelectedValue = 932;

表示方法を変更する

DisplayMemberプロパティに関連して、追記します。.NET Framework 2.0からは、FormatStringプロパティやFormatイベントを使って、リストに表示する文字列の書式を指定することができます。これらを使うためには、FormattingEnabledプロパティをtrueにする必要があります。

FormatStringプロパティには、リストにどのように表示するかを、書式指定文字列を使って指定します。書式指定文字列については、「書式を指定して数値を文字列に変換する」や「日時(DateTimeオブジェクト)を文字列に変換する」などをご覧ください。

FormatStringプロパティで指定された書式は、DisplayMemberプロパティで指定された項目の値に対して適応され、表示されます。

以下の例では、エンコーディングのCodePageプロパティを、"00000"という書式で表示しています。

VB.NET
コードを隠すコードを選択
ListBox1.DisplayMember = "CodePage"
ListBox1.DataSource = System.Text.Encoding.GetEncodings()

'FormatStringの設定を有効にする
ListBox1.FormattingEnabled = True
'書式を指定する
ListBox1.FormatString = "00000"
C#
コードを隠すコードを選択
ListBox1.DisplayMember = "CodePage";
ListBox1.DataSource = System.Text.Encoding.GetEncodings();

//FormatStringの設定を有効にする
ListBox1.FormattingEnabled = true;
//書式を指定する
ListBox1.FormatString = "00000";

Formatイベントを使えば、もっと複雑なことができます。Formatイベントハンドラで取得できるListControlConvertEventArgsオブジェクトのValueプロパティに、リストに表示させたい文字列を設定することができます。

以下の例では、Formatイベントを使って、リストにDisplayNameとCodePageを表示するようにしています。

VB.NET
コードを隠すコードを選択
'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _
        Handles MyBase.Load
    ListBox1.DisplayMember = "CodePage"
    ListBox1.DataSource = System.Text.Encoding.GetEncodings()

    'FormatStringの設定を有効にする
    ListBox1.FormattingEnabled = True
End Sub

'ListBox1のFormatイベントハンドラ
Private Sub ListBox1_Format(ByVal sender As Object, _
                            ByVal e As ListControlConvertEventArgs) _
                            Handles ListBox1.Format
    '文字列が要求されているときだけ変える
    If e.DesiredType Is GetType(String) Then
        'DisplayNameとCodePageを表示するように変更する
        e.Value = CType(e.ListItem, System.Text.EncodingInfo).DisplayName + _
            " : " + e.Value.ToString()
    End If
End Sub
C#
コードを隠すコードを選択
//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    ListBox1.DisplayMember = "CodePage";
    ListBox1.DataSource = System.Text.Encoding.GetEncodings();

    //FormatStringの設定を有効にする
    ListBox1.FormattingEnabled = true;
    //Formatイベントハンドラを追加
    ListBox1.Format += new ListControlConvertEventHandler(ListBox1_Format);
}

//ListBox1のFormatイベントハンドラ
private void ListBox1_Format(object sender, ListControlConvertEventArgs e)
{
    //文字列が要求されているときだけ変える
    if (e.DesiredType == typeof(string))
    {
        //DisplayNameとCodePageを表示するように変更する
        e.Value = ((System.Text.EncodingInfo)e.ListItem).DisplayName +
            " : " + e.Value.ToString();
    }
}

FormatStringプロパティが指定されている場合でも、Formatイベントの結果が優先されるようです。ただし、FormatイベントでValueプロパティの値を変更しなかった場合は、FormatStringプロパティの書式が使われます。

また、FormatイベントのValueプロパティで取得できる値は、FormatStringプロパティが適用されていない値となるようです。

  • 履歴:
  • 2008/7/10 「表示方法を変更する」を追加。また、シャノンさんからのご指摘により、補足の一部を修正。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。