トップ回答者
ListBoxへLINQを使って、文字列を加工しながらデータバインドする方法

質問
-
ADO.NET エンティティデータモデルを使って、LINQ から直接リストボックス(ListBox)へデータバインドする方法を探しています。
Dim ent As New SampleDBEntities ' 更新対象のレコードを検索する Dim q = From t In ent.商品 Select t.商品名, t.単価 ' 結果を表示する ListBox1.DataSource = q.ToList()
のように、Select 句で、二つの列(プロパティ)を並べると、{ 商品名=..., 単価=... } のように表示されてしまうので、これを「商品名 単価(円)」のようにしたいのですが、なにか簡単な方法はないでしょうか?
ListBox の DataSource はデフォルトで ToString を使うので、ToString をオーバーライトしたクラスを使って new すればよいのですが、New With を使って匿名クラスを使う方法があれば、ベターなのですが。
回答
-
結果的に、下記の2つの方法で書けることがわかりました。
■むりやりCTypeでキャストする
VB.NET 専用ですが、integerからStringへの自動キャストを利用しています。
Dim ent As New SampleDBEntities ' 更新対象のレコードを検索する Dim q = From t In ent.商品 Select t.商品名 + " " + CType(t.単価, String) + "円" ListBox1.DataSource = q.ToList
■Formatイベントハンドラを利用する
trapemiya さんの Format イベントハンドラを使う方法
こっちのほうは、String.Format を使えるので成形しやすいかも。
Dim ent As New SampleDBEntities ' 更新対象のレコードを検索する Dim q = From t In ent.商品 Select t.商品名, t.単価 ' 結果を表示する ListBox1.FormattingEnabled = True AddHandler ListBox1.Format, Sub(s, ee) ee.Value = String.Format("{0} {1}円", ee.Value.商品名, ee.Value.単価) ListBox1.DataSource = q.ToList
- 回答としてマーク moonmileMVP 2013年6月11日 4:36
- 編集済み moonmileMVP 2013年6月11日 4:37
-
参考までですが、ListBoxのFormatイベントハンドラでいろいろと加工ができますので、LINQと組み合わせたり、あるいやLINQを全く使わずにFormatイベントハンドラ単体で処理することができます。
(参考)以下のページのFormatイベントハンドラ
DisplayMemberとValueMemberプロパティについて
http://dobon.net/vb/dotnet/control/tbdisplaymember.html★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク moonmileMVP 2013年6月11日 4:35
すべての返信
-
参考までですが、ListBoxのFormatイベントハンドラでいろいろと加工ができますので、LINQと組み合わせたり、あるいやLINQを全く使わずにFormatイベントハンドラ単体で処理することができます。
(参考)以下のページのFormatイベントハンドラ
DisplayMemberとValueMemberプロパティについて
http://dobon.net/vb/dotnet/control/tbdisplaymember.html★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク moonmileMVP 2013年6月11日 4:35
-
結果的に、下記の2つの方法で書けることがわかりました。
■むりやりCTypeでキャストする
VB.NET 専用ですが、integerからStringへの自動キャストを利用しています。
Dim ent As New SampleDBEntities ' 更新対象のレコードを検索する Dim q = From t In ent.商品 Select t.商品名 + " " + CType(t.単価, String) + "円" ListBox1.DataSource = q.ToList
■Formatイベントハンドラを利用する
trapemiya さんの Format イベントハンドラを使う方法
こっちのほうは、String.Format を使えるので成形しやすいかも。
Dim ent As New SampleDBEntities ' 更新対象のレコードを検索する Dim q = From t In ent.商品 Select t.商品名, t.単価 ' 結果を表示する ListBox1.FormattingEnabled = True AddHandler ListBox1.Format, Sub(s, ee) ee.Value = String.Format("{0} {1}円", ee.Value.商品名, ee.Value.単価) ListBox1.DataSource = q.ToList
- 回答としてマーク moonmileMVP 2013年6月11日 4:36
- 編集済み moonmileMVP 2013年6月11日 4:37
-
試すとわかるのですが、残念ながら LINQ to Entities では、ToString が使えません。同じく、String.Format が使えないので、そこが苦労どころなのです。。。
嘘を書いてしまったかと思いあらためて再度確認しましたが、どちらも使えましたよ。
以下検証ソースです。
Public Class Form1 Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load Dim list As New List(Of Entity) For index = 1 To 10 Dim item As New Entity item.商品名 = "商品名" + index.ToString() item.単価 = index list.Add(item) Next Dim listBox As New ListBox() 'listBox.DataSource = (From item In list _ ' Select item.商品名 + " " + item.単価.ToString() + "円").ToList() listBox.DataSource = (From item In list _ Select String.Format("{0} {1}円", item.商品名, item.単価.ToString())).ToList() Me.Controls.Add(listBox) End Sub End Class Public Class Entity Public Sub New() End Sub Public Property 商品名() As String Public Property 単価() As Integer End Class
実行結果
-
aviator__ さんの回答で思いついたのですが、
Dim ent As New SampleDBEntities ' 表示対象のレコードを検索する Dim q = From t In ent.商品.ToList Select String.Format("{0} {1}円", t.商品名, t.単価) ListBox1.DataSource = q.ToList
な風にして、ent.商品.ToList で List に変換してから整形というのありですね。
直接 ToList してしまうと全件が対象になってしまうので、Where 句で絞ったあとに ToList すればフォーマットできる。実際、ListBox に入れるのは絞ったあとの件数になるので、このほうが素直かもしれません。