NonSoft

DataGridViewに便利なメソッドを追加する
サンプル(C#.NET)


 サンプル(ソース/コード)
<このサンプルの概要>
DataGridViewの派生クラスを作って便利なメソッドを追加して行くと高機能のDataGridViewが出来あがります。
.NETで使用するフレックスグリッド(FlexGrid)の代表的な存在?であるDataGridViewなので、自分だけの便利な
メソッドを追加してライバルに差を付けましょう。(と言うかDataGridViewの標準で実装して欲しいのですが)
このサンプルはDataGridViewの使用方法のサンプルとしてもご使用頂けると思います。

このサンプルは以下の機能を実装しています。
(1)DataGridViewのカラム幅をファイルへ保存/読込するための実装
(2)DataGridViewの各カラムへの入力可能文字を制限するための実装
(3)DataGridViewでCtrl-Vキー押下時にクリップボードから貼り付けるための実装
(4)DataGridViewでDelやBackspaceキー押下時にセルの内容を消去するための実装

今後以下の機能の実装を予定しています。
(1)DataGridViewのコンボボックス(ComboBox)をプルダウン(F4)するための実装
(2)DataGridViewのセルの内容をCSV形式で保存するための実装
(3)DataGridViewのセルの内容をHTML形式で保存するための実装
(4)DataGridViewのセルの内容をEXCEL形式で保存するための実装
(5)DataGridViewのセルの内容をDB(ACCESS等)に保存するための実装(DBサンプルとの組み合わせ)
(6)DataGridViewのセルの内容をDB(ACCESS等)から読込むための実装(DBサンプルとの組み合わせ)

ちなみに、このDataGridViewPlusをもっと便利にしているサイトを紹介します。
DataGridViewでコピー&ペーストを可能にする(バインド対応)
DataGridView CSV出力(C#/VB.NET)
DataGridView CSV読込(C#/VB.NET)
DataGridView EXCEL出力(C#/VB.NET)
DataGridView EXCEL読込(C#/VB.NET)
DataGridView HTML出力(C#/VB.NET)

VB.NET版はこちら「DataGridViewに便利なメソッドを追加するサンプル(VB.NET)」です。
また、DataGridViewを使用する上でよく使う技(メモ)は DataGridViewの小技 です。

このサンプルを使用する方法(C#2005の場合)は以下の通りです。
(1)Form1にSystem.Windows.Forms.DataGridViewを追加する
(2)Form1.Designer.vbのSystem.Windows.Forms.DataGridViewの部分をDataGridViewPlusに変更する。
(注)C#2010でForm1.Designer.vbの中のソースを表示するには何らかの設定が必要なようです。。。

★DataGridViewからの派生クラス(DataGridViewPlus.cs)
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace DataGridViewPlus
{
    public class DataGridViewPlus : System.Windows.Forms.DataGridView
    {
        // ----------------------------------------------------------------------------------
        // DataGridViewのカラム幅をファイルへ保存/読込するための実装↓↓↓↓↓↓↓↓↓↓↓↓
        // ----------------------------------------------------------------------------------
        /// <summary>
        /// DataGridViewのカラム幅をXML形式でシリアライズするためのクラス
        /// </summary>
        public class ColWidths
        {
            /// <summary>
            /// カラム幅s
            /// </summary>
            public int[] Widths;
        }

        /// <summary>
        /// DataGridViewのカラム幅をファイルへ保存
        /// </summary>
        /// <remarks>DataGridViewのカラム幅をXML形式でシリアライズ</remarks>
        public void SaveColWidths()
        {
            try
            {
                // EXEファイルのPATH
                String ExePath = System.AppDomain.CurrentDomain.BaseDirectory;
                // XMLファイルのPATH
                String XmlPath = ExePath + "\\" + this.Parent.Name + "_" + this.Name + ".xml";
                // XMLファイルオープン
                StreamWriter sw = new StreamWriter(XmlPath, false, Encoding.Default);
                try
                {
                    // シリアライザー
                    XmlSerializer serializer = new XmlSerializer(typeof(ColWidths));
                    // DataGridViewのカラム幅取得
                    ColWidths colw = new ColWidths();
                    Array.Resize<int>(ref colw.Widths, this.Columns.Count);
                    for (int i = 0; i <= this.Columns.Count - 1; i++)
                    {
                        colw.Widths[i] = this.Columns[i].Width;
                    }
                    // XMLファイル保存
                    serializer.Serialize(sw, colw);
                }
                catch { }
                finally
                {
                    // XMLファイルクローズ
                    if (sw != null) sw.Close();
                }
            }
            catch { }
        }

        /// <summary>
        /// DataGridViewのカラム幅を前回保存したファイルから読込
        /// </summary>
        /// <remarks>DataGridViewのカラム幅をXML形式でデシリアライズ</remarks>
        public void ReadColWidths()
        {
            try
            {
                // EXEファイルのPATH
                String ExePath = System.AppDomain.CurrentDomain.BaseDirectory;
                // XMLファイルのPATH
                String XmlPath = ExePath + "\\" + this.Parent.Name + "_" + this.Name + ".xml";
                // XMLファイルオープン
                StreamReader sr = new StreamReader(XmlPath, Encoding.Default);
                try
                {
                    // シリアライザー
                    XmlSerializer serializer = new XmlSerializer(typeof(ColWidths));
                    // XMLファイル読込
                    ColWidths colw = new ColWidths();
                    colw = (ColWidths)(serializer.Deserialize(sr));
                    // DataGridViewにカラム幅設定
                    for (int i = 0; i <= this.Columns.Count - 1; i++)
                    {
                        this.Columns[i].Width = colw.Widths[i];
                    }
                }
                catch { }
                finally
                {
                    if (sr != null) sr.Close();
                }
            }
            catch { }
        }
        // ----------------------------------------------------------------------------------
        // DataGridViewのカラム幅をファイルへ保存/読込するための実装↑↑↑↑↑↑↑↑↑↑↑↑
        // ----------------------------------------------------------------------------------

        // ----------------------------------------------------------------------------------
        // DataGridViewの各カラムへの入力可能文字を制限するための実装↓↓↓↓↓↓↓↓↓↓↓↓
        // ----------------------------------------------------------------------------------
        /// <summary>
        /// カラムへの入力可能文字を指定するための配列
        /// </summary>
        /// <remarks>ColumnChars[0]="1234567890"</remarks>
        public String[] ColumnChars = new String[] { };
        /// <summary>
        /// 編集中のカラム番号
        /// </summary>
        /// <remarks></remarks>
        private int _editingColumn;
        /// <summary>
        /// 編集中のTextBoxEditingControl
        /// </summary>
        /// <remarks></remarks>
        DataGridViewTextBoxEditingControl _editingCtrl;

        public DataGridViewPlus()
        {
            InitializeComponent();
        }

        private void InitializeComponent()
        {
            ((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
            this.SuspendLayout();
            // 
            // DataGridViewPlus
            // 
            this.RowTemplate.Height = 21;
            this.CellEndEdit += 
                new System.Windows.Forms.DataGridViewCellEventHandler(
                this.DataGridViewPlus_CellEndEdit);
            this.EditingControlShowing += 
                new System.Windows.Forms.DataGridViewEditingControlShowingEventHandler(
                this.DataGridViewPlus_EditingControlShowing);
            this.KeyDown += new System.Windows.Forms.KeyEventHandler(
                this.DataGridViewPlus_KeyDown);
            ((System.ComponentModel.ISupportInitialize)(this)).EndInit();
            this.ResumeLayout(false);

        }

        /// <summary>
        /// セルが編集中になった時の処理
        /// </summary>
        /// <param name="sender">イベントの発生元</param>
        /// <param name="e">イベントの情報</param>
        /// <remarks>編集中のTextBoxEditingControlにKeyPressイベント設定</remarks>
        private void DataGridViewPlus_EditingControlShowing(
            object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            // 編集中のカラム番号を保存
            _editingColumn = ((DataGridView)(sender)).CurrentCellAddress.X;
            try
            {
                // 編集中のTextBoxEditingControlにKeyPressイベント設定
                _editingCtrl = ((DataGridViewTextBoxEditingControl)(e.Control));
                _editingCtrl.KeyPress +=
                    new KeyPressEventHandler(DataGridViewPlus_CellKeyPress);
            }
            catch { }
        }

        /// <summary>
        /// セルの編集が終わった時の処理
        /// </summary>
        /// <param name="sender">イベントの発生元</param>
        /// <param name="e">イベントの情報</param>
        /// <remarks>編集中のTextBoxEditingControlからKeyPressイベント削除</remarks>
        private void DataGridViewPlus_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (_editingCtrl != null)
            {
                // 編集中のTextBoxEditingControlからKeyPressイベント削除
                _editingCtrl.KeyPress -=
                    new KeyPressEventHandler(DataGridViewPlus_CellKeyPress);
                _editingCtrl = null;

            }
        }

        /// <summary>
        /// 編集中のTextBoxEditingControlのKeyPressの処理
        /// </summary>
        /// <param name="sender">イベントの発生元</param>
        /// <param name="e">イベントの情報</param>
        /// <remarks>力可能文字の判定</remarks>
        private void DataGridViewPlus_CellKeyPress(object sender, KeyPressEventArgs e)
        {
            // カラムへの入力可能文字を指定するための配列が指定されているかチェック
            if (ColumnChars.GetType().IsArray)
            {
                // カラムへの入力可能文字を指定するための配列数チェック
                if (ColumnChars.GetLength(0) - 1 >= _editingColumn)
                {
                    // カラムへの入力可能文字が指定されているかチェック
                    if (ColumnChars[_editingColumn] != "")
                    {
                        //カラムへの入力可能文字かチェック
                        if (ColumnChars[_editingColumn].IndexOf(e.KeyChar) < 0 &&
                            e.KeyChar != (char)Keys.Back)
                        {
                            // カラムへの入力可能文字では無いので無効
                            e.Handled = true;
                        }
                    }
                }
            }
        }
        // ----------------------------------------------------------------------------------
        // DataGridViewの各カラムへの入力可能文字を制限するための実装↑↑↑↑↑↑↑↑↑↑↑↑
        // ----------------------------------------------------------------------------------

        // ----------------------------------------------------------------------------------
        // DataGridViewでCtrl-Vキー押下時にクリップボードから貼り付けるための実装↓↓↓↓↓↓
        // DataGridViewでDelやBackspaceキー押下時にセルの内容を消去するための実装↓↓↓↓↓↓
        // ----------------------------------------------------------------------------------
        private void DataGridViewPlus_KeyDown(object sender, KeyEventArgs e)
        {
            DataGridView dgv = (DataGridView)(sender);
            int x = dgv.CurrentCellAddress.X;
            int y = dgv.CurrentCellAddress.Y;
            if (e.KeyCode == Keys.Delete || e.KeyCode == Keys.Back)
            {
            // セルの内容を消去
                dgv[x, y].Value = "";
            }
            else if ((e.Modifiers & Keys.Control) == Keys.Control && e.KeyCode == Keys.V)
            {
                // クリップボードの内容を取得
                String clipText = Clipboard.GetText();
                // 改行を変換
                clipText = clipText.Replace("\r\n", "\n");
                clipText = clipText.Replace("\r", "\n");
                // 改行で分割
                String[] lines = clipText.Split('\n');

                int r;
                Boolean nflag = true;
                for (r = 0; r <= lines.GetLength(0) - 1; r++)
                {
                    // 最後のNULL行をコピーするかどうか
                    if (r >= lines.GetLength(0) - 1 &&
                        "".Equals(lines[r]) && nflag == false) break;
                    if ("".Equals(lines[r]) == false) nflag = false;

                    // タブで分割
                    String[] vals = lines[r].Split('\t');

                    // 各セルの値を設定
                    int c = 0;
                    int c2 = 0;
                    for (c = 0; c <= vals.GetLength(0) - 1; c++)
                    {
                        // セルが存在しなければ貼り付けない
                        if (!(x + c2 >= 0 && x + c2 < dgv.ColumnCount &&
                            y + r >= 0 && y + r < dgv.RowCount))
                        {
                            continue;
                        }
                        // 非表示セルには貼り付けない
                        if (dgv[x + c2, y + r].Visible == false)
                        {
                            c = c - 1;
                            continue;
                        }
                        //// 貼り付け処理(入力可能文字チェック無しの時)------------
                        //// 行追加モード&(最終行の時は行追加)
                        //if (y + r == dgv.RowCount - 1 &&
                        //    dgv.AllowUserToAddRows == true)
                        //{
                        //    dgv.RowCount = dgv.RowCount + 1;
                        //}
                        //// 貼り付け
                        //dgv[x + c2, y + r].Value = vals[c];
                        //// ------------------------------------------------------
                        // 貼り付け処理(入力可能文字チェック有りの時)------------
                        String pststr = "";
                        for (int i = 0; i <= vals[c].Length - 1; i++)
                        {
                            _editingColumn = x + c2;
                            byte[] cc = Encoding.GetEncoding(
                                "SHIFT-JIS").GetBytes(vals[c].Substring(i, 1));
                            KeyPressEventArgs tmpe = new KeyPressEventArgs((char)cc[0]);
                            tmpe.Handled = false;
                            DataGridViewPlus_CellKeyPress(sender, tmpe);
                            if (tmpe.Handled == false)
                            {
                                pststr = pststr + vals[c].Substring(i, 1);
                            }
                        }
                        // 行追加モード&最終行の時は行追加
                        if (y + r == dgv.RowCount - 1 &&
                            dgv.AllowUserToAddRows == true)
                        {
                            dgv.RowCount = dgv.RowCount + 1;
                        }
                        // 貼り付け
                        dgv[x + c2, y + r].Value = pststr;
                        // ------------------------------------------------------
                        // 次のセルへ
                        c2 = c2 + 1;
                    }
                }
            }
        }
        // ----------------------------------------------------------------------------------
        // DataGridViewでCtrl-Vキー押下時にクリップボードから貼り付けるための実装↑↑↑↑↑↑
        // DataGridViewでDelやBackspaceキー押下時にセルの内容を消去するための実装↑↑↑↑↑↑
        // ----------------------------------------------------------------------------------
    }
}

★テスト用フォーム(Form1.cs)
// 予めFrom1にSystem.Windows.Forms.DataGridViewを追加してください。
// そしてForm1.Designer.vbのSystem.Windows.Forms.DataGridViewの部分を
// DataGridViewPlusに変更してください。
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        // セル選択モード
        dataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect;
        // 行ヘッダー無し
        dataGridView1.RowHeadersVisible = false;
        // カラムヘッダーは中央表示
        dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = 
            DataGridViewContentAlignment.MiddleCenter;

        // カラムの追加
        // TextBoxカラムの追加
        dataGridView1.Columns.Add("aaa", "AAA");
        dataGridView1.Columns.Add("bbb", "BBB");
        //DataGridView1.Columns.Add("ccc", "CCC");
        // ComboBoxカラムの追加
        DataGridViewComboBoxColumn cbo = new DataGridViewComboBoxColumn();
        cbo.HeaderText = "CCC";
        cbo.Name = "ccc";
        int i;
        for( i = 1 ;i<= 30;i++){
            cbo.Items.Add("" + i);
        }
        dataGridView1.Columns.Add(cbo);

        // 各カラムを編集可能に設定
        for (i = 0; i <= dataGridView1.Columns.Count - 1; i++)
        {
            dataGridView1.Columns[i].ReadOnly = false;
        }

        // 行の追加
        dataGridView1.Rows.Clear();
        dataGridView1.Rows.Add();
        dataGridView1.Rows[0].Cells[0].Value = "11";
        dataGridView1.Rows[0].Cells[1].Value = "12";
        dataGridView1.Rows[0].Cells[2].Value = "13";
        dataGridView1.Rows.Add();
        dataGridView1.Rows[1].Cells[0].Value = "21";
        dataGridView1.Rows[1].Cells[1].Value = "22";
        dataGridView1.Rows[1].Cells[2].Value = "23";

        // DataGridViewのカラム幅読込
        dataGridView1.ReadColWidths();

        // DataGridViewの入力可能文字指定
        String[] ColumnChars = new String[] { };
        //ReDim ColumnChars(DataGridView1.Columns.Count - 1);
        Array.Resize<String>(ref ColumnChars, dataGridView1.Columns.Count);

        ColumnChars[0] = "abc";
        ColumnChars[1] = "123";
        ColumnChars[2] = "";
        dataGridView1.ColumnChars = ColumnChars;
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
        // DataGridViewのカラム幅保存
        dataGridView1.SaveColWidths();
    }
}

★ちなみに・・・DataGridViewを使用する上でよく使う技
・DataGridViewの行追加方法
  dataGridView1.Rows.Add();

・DataGridViewの行削除方法
  dataGridView1.Rows.RemoveAt(0);

・DataGridViewのカラム削除方法(カラムヘッダも削除されます)
  dataGridView1.Columns.RemoveAt(0);

・DataGridViewの全行削除方法(注意:カラム幅の自動モードで例外が発生する可能性有り)
  dataGridView1.Rows.Clear();

・DataGridViewの指定カラムでソートする方法
  dataGridView1.Sort(DataGridView1.Columns[0], ListSortDirection.Ascending);

・DataGridViewの行やカラムを入力禁止(ReadOnly)にする方法
  dataGridView1.Rows[0].ReadOnly = true;
  dataGridView1.Columns[0].ReadOnly = true;

・DataGridViewの指定セルの背景色を変更する方法
 dataGridView1.Rows[i].Cells["clmName"].Style.BackColor = Color.LightSkyBlue;

・DataGridViewに表示する先頭行(スクロール時の先頭行)を変更する方法
 dataGridView1.FirstDisplayedScrollingRowIndex = 10;

・DataGridViewのスクロール範囲でセルが表示されているか確認する方法
  if( dataGridView1.Rows(4).Cells("clmName").Displayed )

・DataGridViewのカレントセルを取得/変更する方法
 string v = dataGridView1.CurrentCell.Value;
 dataGridView1.CurrentCell = dataGridView1.Rows[4].Cells["clmName"];

・DataGridViewのカレントセルのフォーカスを消す方法
  private void DataGridView1_SelectionChanged(object sender, EventArgs e)
  {
      DataGridView dgv = sender:
      dgv.CurrentCell = null;
  }