トップ回答者
DataTableをLINQしてDataGridViewにバインドしたときの、列の指定

質問
-
失礼します。別で質問していた件の、続きとなります。
「ID」「NAME」の2つの列をもつDataTableに対しLINQでデータを抽出し、DataGridViewのDataSourceにバインドし、表示させます。
この部分はアドバイスいただき、できました。
Dim filterDt = From row In dt.AsEnumerable Where row("ID") >= 4
DataGridView1.DataSource = filterDt.CopyToDataTable
今回質問するのは、実際にDataGridViewに表示させる列を指定するのは、です。
いろいろ調べると、LINQの際にSELECT句を使うんじゃないかな、と思いましたが、以下のようになってしまいます。
Dim filterDt = From row In dt.AsEnumerable Where row("ID") >= "4" Select row("NAME")
エラー 1 'CopyToDataTable' は 'System.Data.EnumerableRowCollection(Of Object)' のメンバーではありません。・・・
どうすれば、表示させる列を指定できるのでしょうか?(またはできない??)
回答
-
Select row("NAME")でNAMEを返すようにした時点で、DataRowを返さなくなりますから、CopyToDataTableは使用できません。DataGridViewにバインドすることを考慮して、代わりにToListを使います。
しかし、まだこれだけではダメです。最終的にToListはstring型の配列を返します。これをDataGridViewにバインドした場合、DataGridViewは最初のパブリックプロパティにバインドしようとしますから、string型配列の最初のパブリックプロパティであるLengthにバインドします。結果的にDataGridViewにはLengthが表示されてしまします。これを防ぐにはToListの結果がstring配列にならないようにすることです。よって、以下のように匿名型でラップして返すようにすればうまく行きます。
Dim filterDt = From row In dt.AsEnumerable Where row("ID") >= 4 Select New With {.NAMEという列名にするよ= row("NAME")} DataGridView1.DataSource = filterDt.ToList()
ちなみに、以下のように2列以上を指定すると勝手に匿名型でラップしてくれますから、以下でうまく行きます。
Dim filterDt = From row In dt.AsEnumerable Where row("ID") >= 4 Select IDという列名にするよ = row("ID"), Nameという列名にするよ = row("Name")
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
-
SQLっぽく単純にはいかないんですね。。。列を削除する案も検討したいと思います。
おそらく、以下のスレッドの続きですよね?
DataTableをLINQしてDataGridViewのDataSourceに設定
http://social.msdn.microsoft.com/Forums/ja-JP/vbexpressja/thread/6c98b6d3-aca6-418e-a874-081b032df404上のスレッドで絞り込み、DataGridViewにバインドしているのはDataTableです。ここから表示したい列だけDataGridViewに表示するのであれば、DataGridViewのAutoGenerateColumnsプロパティをFalseにし、表示したい列のみ指定すれば可能です。これであれば、DataGridViewのDataSourceにはDataTableがバインドしていますから、そのままでDataTableを取得することができます。
(参考)
DataGridViewに列を手動で追加する
http://dobon.net/vb/dotnet/datagridview/addcolumn.htmlLINQの質問はピンポイントであり、それに対する回答が得られたとしても、最終的にどのようなことをされたいのかがわからないので、全体として適切なアドバイスになっていないかもしれません。この辺りを整理されて、あまりスレッドのタイトルとかけ離れた話題が続くようであれば、一旦このスレッドを閉めて、新たにスレッドを開くようにお願いします。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク アースワーム 2012年7月24日 0:22
すべての返信
-
Select row("NAME")でNAMEを返すようにした時点で、DataRowを返さなくなりますから、CopyToDataTableは使用できません。DataGridViewにバインドすることを考慮して、代わりにToListを使います。
しかし、まだこれだけではダメです。最終的にToListはstring型の配列を返します。これをDataGridViewにバインドした場合、DataGridViewは最初のパブリックプロパティにバインドしようとしますから、string型配列の最初のパブリックプロパティであるLengthにバインドします。結果的にDataGridViewにはLengthが表示されてしまします。これを防ぐにはToListの結果がstring配列にならないようにすることです。よって、以下のように匿名型でラップして返すようにすればうまく行きます。
Dim filterDt = From row In dt.AsEnumerable Where row("ID") >= 4 Select New With {.NAMEという列名にするよ= row("NAME")} DataGridView1.DataSource = filterDt.ToList()
ちなみに、以下のように2列以上を指定すると勝手に匿名型でラップしてくれますから、以下でうまく行きます。
Dim filterDt = From row In dt.AsEnumerable Where row("ID") >= 4 Select IDという列名にするよ = row("ID"), Nameという列名にするよ = row("Name")
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
-
ありがとうございます!ご指摘の方法で、表示できました。
が、いただいたソースをコピペしただけでは成長しません。「匿名型」・・・。勉強します。
さて、ついでなのですが、やりたいことには続きがあります。これは今まで以上に愚問かもしれませんが・・・、
DataGridView1.DataSource = filterDt.ToList()
でバインドしたDataGridView1の「表示されているデータ」を別のDataTable(=dt2)にコピーしたいと考えています。で、以下を書いたのですが、
Dim dt2 As DataTable
dt2= DataGridView1.DataSource型 'VB$AnonymousType_0`2[System.Object,System.Object][]' のオブジェクトを型 'System.Data.DataTable' にキャストできません。
となってしまいます。エラーになる理由はなんとなくわかるような気がします、が、はっきりとはわかりません。。。
List型?をDataTableに変換しないといけないのかな。。。 -
みなさん、ありがとうございます。
SQLっぽく単純にはいかないんですね。。。列を削除する案も検討したいと思います。
で、もはやLINQではないんですが、DataTableのSelectメソッドで、絞ることは可能なんでしょうか?
とあるサイトに
---
DataTable.Selectメソッドを用いて
Select("ID, name,…")として取得したDataRow配列をDataTableにセットすることで
---
というのがありました。ためしに
dt.Select("ID,NAME")
としてみたんですが、「式に構文エラーがあります」とでてしまいます。。。
SQLのSELECTとは違う?
-
datagridviewにて表示したくない列のvisibleをfalseにするだけでは、不足でしょうか?
DataGridView1.Columns("表示したくない列").Visible = False
- 編集済み nplaceazure 2012年6月1日 10:30 誤字
-
SQLっぽく単純にはいかないんですね。。。列を削除する案も検討したいと思います。
おそらく、以下のスレッドの続きですよね?
DataTableをLINQしてDataGridViewのDataSourceに設定
http://social.msdn.microsoft.com/Forums/ja-JP/vbexpressja/thread/6c98b6d3-aca6-418e-a874-081b032df404上のスレッドで絞り込み、DataGridViewにバインドしているのはDataTableです。ここから表示したい列だけDataGridViewに表示するのであれば、DataGridViewのAutoGenerateColumnsプロパティをFalseにし、表示したい列のみ指定すれば可能です。これであれば、DataGridViewのDataSourceにはDataTableがバインドしていますから、そのままでDataTableを取得することができます。
(参考)
DataGridViewに列を手動で追加する
http://dobon.net/vb/dotnet/datagridview/addcolumn.htmlLINQの質問はピンポイントであり、それに対する回答が得られたとしても、最終的にどのようなことをされたいのかがわからないので、全体として適切なアドバイスになっていないかもしれません。この辺りを整理されて、あまりスレッドのタイトルとかけ離れた話題が続くようであれば、一旦このスレッドを閉めて、新たにスレッドを開くようにお願いします。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク アースワーム 2012年7月24日 0:22