Utils/DataGridViewDestinationExtensions.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using ChatworkBulkSender.Dtos;

namespace ChatworkBulkSender.Utils
{
    public static class DataGridViewDestinationExtensions
    {
        /// <summary>
        /// グリッドの初期化
        /// </summary>
        public static void InitializeDestinationGrid(this DataGridView dgv, TextBox txtActualContents)
        {
            // 列の自動生成を行わない
            dgv.AutoGenerateColumns = false;
            // 行ヘッダ非表示
            dgv.RowHeadersVisible = false;
            // ユーザーによる行の高さ変更を禁止
            dgv.AllowUserToResizeRows = false;
            // 編集不可
            dgv.ReadOnly = true;
            // 行単位で選択する形式とする
            dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            // 複数選択不可
            dgv.MultiSelect = false;
            // イベント設定
            AttachDestinationGridEvents(dgv, txtActualContents);
        }

        /// <summary>
        /// DestinationList をバインドし、列を追加する
        /// </summary>
        public static void SetupDestinationAndFilePathGrid(this DataGridView dgv)
        {
            dgv.Columns.Clear();
            dgv.Columns.Add(new DataGridViewTextBoxColumn
            {
                DataPropertyName = nameof(CustomerMasterDto.ManagementNumber),
                HeaderText = "管理番号",
                Width = 120,
                ReadOnly = true
            });
            dgv.Columns.Add(new DataGridViewTextBoxColumn
            {
                DataPropertyName = nameof(CustomerMasterDto.CustomerName),
                HeaderText = "顧客名",
                Width = 400,
                ReadOnly = true
            });
            dgv.Columns.Add(new DataGridViewTextBoxColumn
            {
                DataPropertyName = nameof(CustomerMasterDto.FilePath),
                HeaderText = "ファイルパス",
                Width = 900,
                ReadOnly = true
            });
            dgv.Columns.Add(new DataGridViewTextBoxColumn
            {
                DataPropertyName = nameof(CustomerMasterDto.SendActualContents),
                HeaderText = "送信内容",
                Visible = false,
                ReadOnly = true
            });
        }

        /// <summary>
        /// データをバインドする
        /// </summary>
        public static void BindDestinationData(this DataGridView dgv, IEnumerable<CustomerMasterDto> source)
        {
            dgv.DataSource = source.ToList();
        }

        /// <summary>
        /// ダブルクリック・クリック時のイベントを紐付ける
        /// </summary>
        private static void AttachDestinationGridEvents(this DataGridView dgv, TextBox txtActualContents)
        {
            // イベントハンドラをメソッド参照で登録
            dgv.CellDoubleClick += OnDestinationGridCellDoubleClick;
            dgv.CellClick += OnDestinationGridCellClick;
            dgv.SelectionChanged += OnDestinationGridSelectionChanged;
            dgv.DataBindingComplete += OnDestinationGridDataBindingComplete;

            // ダブルクリックイベント
            void OnDestinationGridCellDoubleClick(object sender, DataGridViewCellEventArgs e)
            {
                // ヘッダー行など無効な行は無視
                if (e.RowIndex < 0) return;

                // DataBoundItem から DTO を取得
                var grid = (DataGridView)sender;
                var dto = grid.Rows[e.RowIndex].DataBoundItem as CustomerMasterDto;
                if (dto?.FilePath == null) return;

                // ファイルが見つからない場合エラー
                if (!File.Exists(dto.FilePath))
                {
                    MessageBoxUtil.ShowErr(MessageBoxUtil.ERR_101);
                    return;
                }

                // 規定アプリで開く
                try
                {
                    Process.Start(dto.FilePath);
                }
                catch (Exception ex)
                {
                    MessageBoxUtil.ShowErr(string.Format(MessageBoxUtil.ERR_102, ex.Message));
                }
            }

            // クリックイベント
            void OnDestinationGridCellClick(object sender, DataGridViewCellEventArgs e)
            {
                UpdateActualContents(e.RowIndex);
            }

            // 選択セル変更イベント
            void OnDestinationGridSelectionChanged(object sender, EventArgs e)
            {
                var grid = (DataGridView)sender;
                if (grid.CurrentRow != null)
                    UpdateActualContents(grid.CurrentRow.Index);
            }

            // 選択中の送信先に送ることになる送信内容を表示
            void UpdateActualContents(int rowIndex)
            {
                if (rowIndex < 0) return;
                var dto = dgv.Rows[rowIndex].DataBoundItem as CustomerMasterDto;
                txtActualContents.Text = dto?.SendActualContents ?? string.Empty;
            }

            // バインド完了時、1行目のデータを初期選択する
            void OnDestinationGridDataBindingComplete(object sender, EventArgs e)
            {
                if (dgv.Rows.Count > 0)
                {
                    // 最初の行を選択状態にする
                    dgv.ClearSelection();
                    dgv.Rows[0].Selected = true;
                    // 送信内容を表示
                    UpdateActualContents(0);
                }
            }
        }
    }
}