C#使用visual studioのdatagridView新規追行の入力値検証方法

前提

(1)C#でvisual studioとMs SQL ServerとでWindowsフォームアプリケーション住所録を作成しています。
登録データの個々の属性マスター(親戚、友人、知人・・・等)のテーブルKuwakeTblを下記の様なフィールドで作成しました。
(2)このデータの編集にDataGridViewとBindingNavigatorをBindingsource経由でフォームに作成。
テーブルのKuwakeNameフィールドは必須入力、重複不可、HyoujiNo(属性により個々データを重要なものから表示)フィールドは必須入力指定です。
(3)入力中のデータ検証のためDataGridViewのCellValidatingメソッドに下記のコードを作りました。
(4)動作検証の為BindingNavigatorにボタンおよびFormにボタンをそれぞれ作成しClickメソッドにそれぞれメッセージ表示させるコートを作成。

「動作状況」
①グリッド内で既存データ行での移動はBindingNavigatorでの行移動を含め正常に動作
②グリッド下端の新規追加行に移動後何も操作せず又は何らかの入力作業後グリッド内の他のセルに「マウス、矢印キー、Tabキー等」で移動は正常
③グリッド下端の新規追加行に移動後何も操作せず又は何らかの入力作業後BindingNavigatorで行移動すると下記Program.csの「エラー発生行」コメント部に「System.Data.NoNullAllowedException: '列 'KuwakeName' に nulls を使用することはできません」のエラー発生。
この場合CellValidatingメソッドが実行された場合表示されるメッセージは発生しません。
④グリッド下端の新規追加行に移動後何も操作せず又は何らかの入力作業後Formに作ったボタンをクリック後BindingNavigatorで行移動すると正常に動作するのに対し、BindingNavigator内に作成したボタンをクリック後BindingNavigatorで行移動すると③と同様のエラー発生。

「気付いたこと」
①DataGridViewの最左端列には現在行のマーク「▶」、新規行マーク「*」がありますが最初の状態は第1行に「▶」が有り最下端に「*」が有ります。新規行に移動すると「▶*」に変ります。この2マーク表示状態ではマウス等でのグリッド内移動は正常ですがBindingNavigatorでの移動はエラー発生します。
②前項と同様にして新規行に移動し「▶*」表示状態でFormに作成した「ボタン」をマウスでクリックすると「*」は新規行に残り、「▶」は1行上に表示されます。このため以後はBindingNavigatorでの移動は正常です。

「解決したいこと」
汎用の必須入力、重複検証はどのようにするのが適当なのでしょうか?
特に新規追加行の場合元々全入力欄が空白でセルを移動して入力していきます、ただし無入力又は一部入力途中で止めて新規追加をキャンセルすることがあります(一部入力時は新規追加行のプロパティNewRowIndexは持たなくなるようです)。
ご教授ください。

発生している問題・エラーメッセージ

エラーメッセージ System.Data.NoNullAllowedException: '列 'KuwakeName' に nulls を使用することはできません。'

該当のソースコード

ソースコード (1)「テーブル定義」 CREATE TABLE [dbo].[CsKuwakeTbl] ( [KuwakeId] INT IDENTITY (1, 1) NOT NULL, [KuwakeName] NVARCHAR (30) NOT NULL, [HyoujiNo] INT NOT NULL, CONSTRAINT [PK_CsKuwakeTbl] PRIMARY KEY CLUSTERED ([KuwakeId] ASC), UNIQUE NONCLUSTERED ([KuwakeName] ASC) ); (2)「グリッド入力値チェックコード」 private void csKuwakeTblDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) { //セル入力データ検証に入った目印 MessageBox.Show("CellValidating"); //------区分名編集タブ内グリッド内での必須入力及び区分名の重複検証 DataGridView dgv = (DataGridView)sender; //種々のチェックでデータベースへの登録の可否flg int flg = 0; //セル移動の可否 flg= 0 可 // ① 行内でデータ変更無の時は無検証 if (!dgv.IsCurrentRowDirty) { flg = 1; return; } // ② 既存行でのセル移動検証 if (e.RowIndex != dgv.NewRowIndex) { // 区分名、表示順は空白不可 if ((e.FormattedValue.ToString() == "") || (e.FormattedValue == null)) { // 空白不可 flg = 1; MessageBox.Show("区分名又は表示順が空白です。元の値に戻します"); //元の値に戻し、セルを元の位置に戻す dgv.CancelEdit(); e.Cancel = true; return; } } // ③ 区分名は重複不可検証 if (flg == 0 & e.ColumnIndex == 0) { //重複検証 foreach (DataGridViewRow row in dgv.Rows) { if (row.Index != e.RowIndex) { // 編集中の行どうしでないとき if (row.Cells[e.ColumnIndex].Value != null) { // 列に値が格納されているとき if (e.FormattedValue.ToString() == row.Cells[e.ColumnIndex].Value.ToString()) { // 値が重複するならエラー表示してループから抜けるv MessageBox.Show("区分名が重複しています。元の値に戻します"); //元の値に戻し、セルを元の位置に戻す flg = 1; break; } } } } //区分名が重複の時は不可 if (flg == 1) { dgv.CancelEdit(); e.Cancel = true; return; } // ④ 新規追加行で処理 //区分名、表示順の一方のみ入力は行移動可(全項目入力済みでのセル移動時はデータベースへ登録) if (flg == 0 & (e.RowIndex == dgv.NewRowIndex)) { .int n = 0; //全コラム数 int m = 0; //入力の有るコラム数 //追加行のセルがすべて空かを調べる foreach (DataGridViewCell cell in dgv.Rows[e.RowIndex].Cells) { n = n + 1; if (cell.Value != null || cell.Value.ToString() != "") { //未入力セル数 m = m + 1; } } //新規追加行では行内でのセル移動は自由。全欄入力済みの時はデータベース登録 if (n != m) { //一部欄のみ入力時はデータベース登録無。行内セル移動可 //全欄空白時はn=2,m=0となり、ここに入ってくる flg = 1; //データベースへ登録なし } } } // ⑤ 入力値チェックOKでデータベース登録 if (flg == 0) { //何れかのセルに入力が有り、データ検証OKのデータをデータベースに登録 this.Validate(); this.csPostTblBindingSource.EndEdit(); this.tableAdapterManager.UpdateAll(this.csPostDbDataSet); } } (3)「エラー表示部コード」(下記再下端行 Application.Run(new Form1()); 部分にエラー表示) namespace CsPostApp { internal static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); //----------------この行にエラー発生表示 Application.Run(new Form1()); } } }

コメントを投稿

0 コメント