はじめに
C# ソフト開発時に、決まり事として実施していた内容を記載します。
DataGridView については下記記事もあります
- Windows Forms C#定石 - DataGridView - EditMode, DropDown
- Windows Forms C#定石 - DataGridView - ReadOnly, Disable相当
- Windows Forms C#定石 - DataGridView - DataTable
テスト環境
ここに記載した情報/ソースコードは、Visual Studio Community 2022 を利用した下記プロジェクトで生成したモジュールを Windows 11 24H2 で動作確認しています。
- Windows Forms - .NET Framework 4.8
- Windows Forms - .NET 8
記載したソースコードは .NET 8 ベースとしています。
.NET Framework 4.8 の場合は、コメントで記載している null 許容参照型の明示 ?
を削除してください。
Visual Studio 2022 - .NET Framework 4.8 は、C# 7.3 が既定です。
このため、サンプルコードは、C# 7.3 機能範囲で記述しています。
値依存イメージ表示
Dev Q&A: DataGridView | Microsoft Learn で、Figure 5 Custom Image Column for the DataGridView として記載されている手法があります。
この手法だと、DataGridViewImageCell 派生クラス( CustomImageCell )に固定イメージを設定しているので、異なるイメージを利用する場合には、別クラスを作成しなければなりません。
そこで、DataGridViewImageColumn 派生クラスにイメージを保持して、イメージを設定可能としています。
// 数値に関係づけられたイメージを表示する DataGridViewCell
public class DataGridViewBindImageColumn : DataGridViewImageColumn
{
// 初期値を設定しておかないと、意図した動作にならない
public Image[] BindImages { get; set; } = new Image[] {
SystemIcons.Application.ToBitmap() };
public DataGridViewBindImageColumn()
{
this.CellTemplate = new DataGridViewBindImageCell();
this.ValueType = typeof(int);
this.ImageLayout = DataGridViewImageCellLayout.Zoom;
this.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
}
}
public class DataGridViewBindImageCell : DataGridViewImageCell
{
public DataGridViewBindImageCell()
{
this.ValueType = typeof(int);
}
// .NET Framework 時 object? の ? 不要
protected override object? GetFormattedValue(
object value, int rowIndex, ref DataGridViewCellStyle cellStyle,
TypeConverter valueTypeConverter,
TypeConverter formattedValueTypeConverter,
DataGridViewDataErrorContexts context)
{
if (this.OwningColumn is DataGridViewBindImageColumn column
&& column.BindImages != null
&& Value is int index
&& index >= 0 && index < column.BindImages.Length)
{
return column.BindImages[index];
}
return null;
}
// 行追加時の既定値
public override object DefaultNewRowValue => -1;
}
上記の利用方法を記載します。
// DataGridView 設定
dataGridView1.AllowUserToResizeRows = false;
dataGridView1.AutoGenerateColumns = false;
dataGridView1.MultiSelect = false; // 複数選択無効
dataGridView1.ColumnHeadersVisible = true; // 列ヘッダ表示
dataGridView1.RowHeadersVisible = false; // 行ヘッダ非表示
dataGridView1.AllowUserToDeleteRows = false; // 削除キーで削除を無効
dataGridView1.AllowUserToAddRows = false; // 末尾行での行追加を無効
dataGridView1.ScrollBars = ScrollBars.Both;
dataGridView1.ColumnHeadersHeight = 28;
dataGridView1.Columns.AddRange(new DataGridViewColumn[]
{
new DataGridViewTextBoxColumn { Name = "ID", Width = 30, ReadOnly = true },
new DataGridViewBindImageColumn { Name = "Default", Width = 50 },
new DataGridViewBindImageColumn { Name = "Status", Width = 50,
BindImages = new Image[] {
SystemIcons.Information.ToBitmap(),
SystemIcons.Question.ToBitmap(),
SystemIcons.Warning.ToBitmap(),
SystemIcons.Error.ToBitmap() } }
});
// テストデータ
dataGridView1.Rows.Clear();
for (int no = 0; no < 5; no++)
{
DataGridViewRow row = new DataGridViewRow();
row.CreateCells(dataGridView1);
row.Height = 30;
row.Cells[0].Value = no;
row.Cells[1].Value = no;
row.Cells[2].Value = no;
dataGridView1.Rows.Add(row);
}
ちらつき防止
DoubleBuffered
[C#]DataGridViewのDoubleBufferedを有効にする
方法: フォームとコントロールのダブル バッファリングでグラフィックスのちらつきを軽減する
DataGridView を使ってみると、表示が重いことから、ちらつきが気になることがあります。
この表示の重さは、DoubleBuffered プロパティを有効にすることによって、改善が期待できます。
DataGridView では、DoubleBuffered プロパティが protected となってしまっているので直接アクセスできませんが、リフレクションを使用して設定することが可能です。
using System.Reflection;
this.Load += Form1_Load;
// .NET Framework 時 object? の ? 不要
private void Form1_Load(object? sender, EventArgs e)
{
// デザイナで DataGridView dataGridView1, dataGridView2 を配置
var info = typeof(DataGridView).GetProperty("DoubleBuffered",
BindingFlags.Instance | BindingFlags.NonPublic);
info?.SetValue(dataGridView1, true, null);
info?.SetValue(dataGridView2, true, null);
}
下記手法で Form 全体をダブルバッファリングさせることもできますが、複雑な UI を描画する際にはパフォーマンスに影響を与える可能性があります。
// 対象 Form クラスに追加
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // WS_EX_COMPOSITED 追加
return cp;
}
}
再描画の一時停止
DataGirdView のデフォルト動作では、行追加などの操作毎に DataGridView の再描画が発生して、画面がちらついてしまうことがあります。
この対策としては、SuspendLayout と ResumeLayout を使用して再描画を一時停止、再開することで、ちらつきを抑えることができます。
// デザイナで DataGridView dataGridView1 を配置
// 一時停止
Cursor cursor = this.Cursor;
this.Cursor = Cursors.WaitCursor;
dataGridView1.SuspendLayout();
// TODO - データ更新とソート
// 再開
dataGridView1.ResumeLayout();
this.Cursor = cursor;