C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: DataGridViewのソート処理について


(過去ログ 173 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■99880 / inTopicNo.1)  DataGridViewのソート処理について
  
□投稿者/ はるぱぱ (1回)-(2022/06/15(Wed) 16:18:08)

分類:[.NET 全般] 

Visual Studio2019です。

DataGridViewにて表を作成しました。
ヘッダー部のクリックによってソートが行えますが、
Int列においてソートを行うと上部にnullが来てその後1から数字が昇順でソートされます。
SQLServerの仕様のようですがこれを1〜順に昇順で最後にNULLが来るようにするにはどのようにすればいいでしょうか。
引用返信 編集キー/
■99882 / inTopicNo.2)  Re[1]: DataGridViewのソート処理について
□投稿者/ 魔界の仮面弁士 (3402回)-(2022/06/15(Wed) 17:34:00)
No99880 (はるぱぱ さん) に返信
> 分類:[.NET 全般] 
言語指定が無いので、とりあえず C# で書きます。


> SQLServerの仕様のようですがこれを1〜順に昇順で最後にNULLが来るようにするにはどのようにすればいいでしょうか。
DataGridView のソート仕様は、SQL Server の仕様とは無関係ですよ。

ADO.NET をお使いとは思いますが、DataGridView が見ているのは
あくまでも DataTable のデータに過ぎません。

そしてその DataTable の内容が
CSV から取り込まれたものなのか、
SQL Server から取り込まれたのかといった事情は、
DataGridView にとっては何の関係も無い事です。


SQL Server で NULL を末尾にしてソートする場合は
 ORDER BY num ASC
の代わりに
 ORDER BY ISNULL(num,0x7fffffff) ASC
のようにします。ちなみに Oracle の場合は、
 ORDER BY num ASC NULLS LAST
です。


> ヘッダー部のクリックによってソートが行えますが、
ソートができるかどうかは、DataSource 次第ですけれどね。

DataSource が指定されていない場合は、
SortCompare イベントを使ってカスタムソートを実装できます。
https://dobon.net/vb/dotnet/datagridview/customsort.html

DataSource を指定しつつ、カスタムソートを実装したい場合には、
独自ソート機構を持ったデータソースを用意する方法があります。
https://garafu.blogspot.com/2016/09/cs-sorablebindinglist.html


取りあえず今回は、DataTable や DataView がセットされているものと仮定します。
private DataTable CreateSampleTable()
{
  var tbl = new DataTable();
  tbl.PrimaryKey = new DataColumn[] { tbl.Columns.Add("id", typeof(int)) };
  tbl.Columns.Add("num", typeof(int));
  tbl.Rows.Add(1, 1000);
  tbl.Rows.Add(2, 3000);
  tbl.Rows.Add(3, DBNull.Value);
  tbl.Rows.Add(4, 2000);
  tbl.AcceptChanges();
  return tbl;
}

private DataTable tbl;
private void Form1_Load(object sender, EventArgs e)
{
  // 実際には SQL Server から取得してきたデータ
  tbl = CreateSampleTable();

  // 型付 DataSet を使っているなら、バインド設定はデザイン時に行っても構わない
  dataGridView1.AutoGenerateColumns = true;
  dataGridView1.DataSource = new DataView(tbl); // DataView のかわりに BindingSource でも可
  // カスタムソートにしたい列は、Programmatic モードにしておく
  dataGridView1.Columns[1].SortMode = DataGridViewColumnSortMode.Programmatic;

  // ソート用の『式列(Expression Column)』を追加する
  // これは DataGridView にはバインドしない(または該当列を Visible = false にしておく)
  dataGridView1.AutoGenerateColumns = false;
  tbl.Columns.Add("numASC", typeof(int), "ISNULL([num], " + int.MaxValue + ")");
  tbl.Columns.Add("numDESC", typeof(int), "ISNULL([num], " + int.MinValue + ")");
}


// 列ヘッダーをクリックされたら、
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
  var dgv = (DataGridView)sender;
  var view = dgv.DataSource as DataView;
  if (view == null || e.ColumnIndex != 1) { return; }

  // Programmatic 列がクリックされた場合は、代わりに「式列」でソートする
  var header = dgv.Columns[1].HeaderCell;
  if (header.SortGlyphDirection == SortOrder.Ascending)
  {
    view.Sort = "[numDESC] DESC";
    header.SortGlyphDirection = SortOrder.Descending;
  }
  else
  {
    view.Sort = "[numASC] ASC";
    header.SortGlyphDirection = SortOrder.Ascending;
  }
}
引用返信 編集キー/
■99884 / inTopicNo.3)  Re[2]: DataGridViewのソート処理について
□投稿者/ 魔界の仮面弁士 (3404回)-(2022/06/15(Wed) 17:50:24)
No99882 (魔界の仮面弁士) に追記
> SQL Server で NULL を末尾にしてソートする場合は
>  ORDER BY num ASC
> の代わりに
>  ORDER BY ISNULL(num,0x7fffffff) ASC
> のようにします。

ISNULL よりも、CASE を使った方が良いですね。


-- ORDER BY num ASC NULLS LAST の代用
ORDER BY CASE WHEN num IS NULL THEN 0 ELSE 1 END ASC, num ASC

-- ORDER BY num DESC NULLS LAST の代用
ORDER BY CASE WHEN num IS NULL THEN 0 ELSE 1 END ASC, num DESC

-- ORDER BY num ASC NULLS FIRST の代用
ORDER BY CASE WHEN num IS NULL THEN 0 ELSE 1 END DESC, num ASC

-- ORDER BY num DESC NULLS FIRST の代用
ORDER BY CASE WHEN num IS NULL THEN 0 ELSE 1 END DESC, num DESC



ということで、DataGridView で対応する場合も同じ方式に差し換えてみる。

> dataGridView1.AutoGenerateColumns = false;
> tbl.Columns.Add("numASC", typeof(int), "ISNULL([num], " + int.MaxValue + ")");
> tbl.Columns.Add("numDESC", typeof(int), "ISNULL([num], " + int.MinValue + ")");
dataGridView1.AutoGenerateColumns = false;
tbl.Columns.Add("numIsNull", typeof(bool), "[num] IS NULL");


> if (header.SortGlyphDirection == SortOrder.Ascending)
> {
>   view.Sort = "[numDESC] DESC";
>   header.SortGlyphDirection = SortOrder.Descending;
> }
> else
> {
>   view.Sort = "[numASC] ASC";
>   header.SortGlyphDirection = SortOrder.Ascending;
> }
if (header.SortGlyphDirection == SortOrder.Ascending)
{
  view.Sort = "[numIsNull] ASC, [num] DESC";
  header.SortGlyphDirection = SortOrder.Descending;
}
else
{
  view.Sort = "[numIsNull] ASC, [num] ASC";
  header.SortGlyphDirection = SortOrder.Ascending;
}
引用返信 編集キー/
■99885 / inTopicNo.4)  Re[3]: DataGridViewのソート処理について
□投稿者/ はるぱぱ (2回)-(2022/06/15(Wed) 17:57:20)
No99884 (魔界の仮面弁士 さん) に返信
魔界の仮面弁士様
長々とありがとうございました。

一旦そのような感じでやってみます。
引用返信 編集キー/
■99894 / inTopicNo.5)  Re[4]: DataGridViewのソート処理について
□投稿者/ はるぱぱ (3回)-(2022/06/16(Thu) 13:52:34)
No99884 (魔界の仮面弁士 さん) に返信

おかげさまでnull排除のソートができました。
ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -