C#のWindows FormでDataGridViewを使用してみる

# 1. はじめに
* DataGridViewの初歩的な使い方を確認したい
* DataGirdViewの設定を変更したい

# 2. 開発環境
* C# ( .NET 8) Window
* Windows フォームアプリ
* Visual Studio 2022
* Windows 11

# 3. 完成画面イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/1c0cebfd-9bed-a1e6-76e6-86f1096c5294.png)

# 4. DataGridViewの設定変更例
## 4.1. DataGridViewとDTOのデータバインド
* Itemクラスを作成して、DataGridViewにデータバインドしてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/1e6acd10-a22b-3da3-76df-e070d2051c54.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/2f12486e-9047-0329-478a-8984a58b67d7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/0224c30a-4353-7857-b27f-0df3bcfe2aac.png)

```Csharp: Form1.cs
namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        private BindingList<Item>? _tasks;
        private bool boolChekOnOff = true;

        public Form1()
        {
            InitializeComponent();
            InitializeDataGridView();
        }

        private void InitializeDataGridView()
        {
            // DataGridViewの行データ追加
            _tasks = new BindingList<Item>();
            Item taskItem1 = new Item() { Name = "山田太郎", Age = 10, Select = false };
            Item taskItem2 = new Item() { Name = "山田次郎", Age = 20, Select = true };
            Item taskItem3 = new Item() { Name = "山田三郎", Age = 30, Select = false };
            _tasks.Add(taskItem1);
            _tasks.Add(taskItem2);
            _tasks.Add(taskItem3);

            // DataGridViewのDataSource設定
            dataGridView1.DataSource = _tasks;
        }
    }
}
```

```Csharp:Item.cs
namespace WinFormsApp1
{
    public class Item
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public bool Select { get; set; }
    }
}
```

## 4.2. 行追加/削除の禁止
* デフォルトは行追加/削除が可能なため、利用できないようにする。
```Csharp:Form1.cs
    // 行追加の禁止
    dataGridView1.AllowUserToAddRows = false;
    // 行削除の禁止
    dataGridView1.AllowUserToDeleteRows = false;
```

## 4.3. 列タイトルの設定
* デフォルトはDTOの変数名になっているので、日本語名を設定する。
```Csharp:Form1.cs
    // 列タイトルを追加
    dataGridView1.Columns[0].HeaderText = "名前";
    dataGridView1.Columns[1].HeaderText = "年齢";
    dataGridView1.Columns[2].HeaderText = "選択";
```

## 4.4. 1クリックで編集可に設定
* 1クリックで編集可能に設定する。
```Csharp:Form1.cs
// 1クリックで編集可に設定
this.dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
```

## 4.5. 行番号を追加
* 先頭列に1から行番号を追加する。
```Csharp:Form1.cs
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (e.ColumnIndex < 0 && 0 <= e.RowIndex)
    {
        // セルを描画
        e.Paint(e.ClipBounds, DataGridViewPaintParts.All);

        // 行番号を描画
        TextRenderer.DrawText(
            e.Graphics,
            (e.RowIndex + 1).ToString(),
            e.CellStyle.Font,
            e.CellBounds,
            e.CellStyle.ForeColor,
            TextFormatFlags.Right | TextFormatFlags.VerticalCenter);

        // 描画完了
        e.Handled = true;
    }
}
```

## 4.6. チェック一括On/Off
* 行タイトルをクリックした時に、チェックボックスの一括On/Offを行う。
```Csharp:Form1.cs
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
    // 選択タイトルをクリックした時
    if (e.RowIndex == -1 && e.ColumnIndex == 2)
    {
        foreach (DataGridViewRow row in dataGridView1.Rows)
        {
            if (row.ReadOnly == false && row.IsNewRow == false)
            {
                row.Cells[2].Value = boolChekOnOff;
            }
        }
         boolChekOnOff = boolChekOnOff ? false : true;
    }
}
```

## 4.7. 行の編集禁止
* 先頭行を編集禁止にする。（Initializeで実行すると動かない）
```Csharp:Form1.cs
private void Form1_Load(object sender, EventArgs e)
{
    // 1行目のみ編集不可にする
    dataGridView1.Rows[0].ReadOnly = true;
    dataGridView1.Rows[0].DefaultCellStyle.BackColor = Color.LightGray;
}
```
## 5. ソースコード（全体）
```Csharp:Form1.cs
using System.ComponentModel;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        private BindingList<Item>? _tasks;
        private bool boolChekOnOff = true;

        public Form1()
        {
            InitializeComponent();
            InitializeDataGridView();
        }

        private void InitializeDataGridView()
        {
            // DataGridViewの行データ追加
            _tasks = new BindingList<Item>();
            Item taskItem1 = new Item() { Name = "山田太郎", Age = 10, Select = false };
            Item taskItem2 = new Item() { Name = "山田次郎", Age = 20, Select = true };
            Item taskItem3 = new Item() { Name = "山田三郎", Age = 30, Select = false };
            _tasks.Add(taskItem1);
            _tasks.Add(taskItem2);
            _tasks.Add(taskItem3);

            // DataGridViewのDataSource設定
            dataGridView1.DataSource = _tasks;

            // 行追加の禁止
            dataGridView1.AllowUserToAddRows = false;
            // 行削除の禁止
            dataGridView1.AllowUserToDeleteRows = false;

            // 列タイトルを追加
            dataGridView1.Columns[0].HeaderText = "名前";
            dataGridView1.Columns[1].HeaderText = "年齢";
            dataGridView1.Columns[2].HeaderText = "選択";

            // 1クリックで編集可に設定
            this.dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
        }

        private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            // 選択タイトルをクリックした時
            if (e.RowIndex == -1 && e.ColumnIndex == 2)
            {
                foreach (DataGridViewRow row in dataGridView1.Rows)
                {
                    if (row.ReadOnly == false && row.IsNewRow == false)
                    {
                        row.Cells[2].Value = boolChekOnOff;
                    }
                }
                boolChekOnOff = boolChekOnOff ? false : true;
            }
        }

        private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.ColumnIndex < 0 && 0 <= e.RowIndex)
            {
                // セルを描画
                e.Paint(e.ClipBounds, DataGridViewPaintParts.All);

                // 行番号を描画
                TextRenderer.DrawText(
                    e.Graphics,
                    (e.RowIndex + 1).ToString(),
                    e.CellStyle.Font,
                    e.CellBounds,
                    e.CellStyle.ForeColor,
                    TextFormatFlags.Right | TextFormatFlags.VerticalCenter);

                // 描画完了
                e.Handled = true;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 1行目のみ編集不可にする
            dataGridView1.Rows[0].ReadOnly = true;
            dataGridView1.Rows[0].DefaultCellStyle.BackColor = Color.LightGray;
        }
    }
}
```

```Csharp:Item.cs
namespace WinFormsApp1
{
    public class Item
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public bool Select { get; set; }
    }
}
```

# 6. 参考文献

https://qiita.com/lusf/items/dcce573787e808ccb0ea

https://learn.microsoft.com/ja-jp/dotnet/desktop/winforms/controls/prevent-row-addition-and-deletion-datagridview?view=netframeworkdesktop-4.8

https://std9.jp/articles/01fmxzvhc3tt8n61ma0mhd7pyc

https://cozver.com/2021/06/12/post-1657/

https://learn.microsoft.com/ja-jp/dotnet/desktop/winforms/controls/how-to-specify-the-edit-mode-for-the-windows-forms-datagridview-control?view=netframeworkdesktop-4.8