none
NoNullAllowedExceptionのエラーをチェックができない RRS feed

  • 質問

  • VisualStudio2013 C# デスクトップアプリケーションの環境です。

    Form1から呼び出したForm2にBindingNavigatorとDBにバインドしたテキストボックスを配置しています。

    Form2のBindingNavigatorの新規登録ボタンをクリックして、新規レコードを登録します。

    プライマリキーを入力せずにBindingNavigatorの「前に戻る」をクリックし、行移動しようとすると

    NoNullAllowedExceptionがprogram.csで発生しますが、それをcatchして処理をしたいと思っています。

    デバッグ中でProgram.csのApplication.Run(new Form1())でエラー中断してしまいます。

    イベントの

    bindingSource1_PositionChanged

    bindingNavigatorMovePreviousItem_Click

    bindingSource1_AddingNew

    でプライマリキーの入力をチェックしようと思いましたが、その前に

    上記のエラーで中断してしまいます。

    ボタンを追加し、クリックされたらプライマリキーのチェックをし、行移動すればOKなのですが、

    bindingNavigatorの行移動ボタンをクリックされると上記のイベントでは引っかかりません。

    どこでチェックしたらいいのでしょうか?

    2014年4月20日 14:31

回答

  • これはおそらく昔からよく言われている、削除ボタンを押した時に削除の確認をしたいという質問と同じ種類のものだと思います。
    BindingNavigatorのこれらのボタンはToolStripItemです。ですから、このOnClickメソッドをオーバーライドしたものを、BindingNavigatorの例えばMoveNextItemプロパティにセットしてやれば良いように思います。例えば以下のような感じです。

    partial class CustomToolStripButton : System.Windows.Forms.ToolStripButton
    {
        protected override void OnClick(EventArgs e)
        {
            //エラーチェックして、問題なければbase.OnClick(e)を実行      
    
            base.OnClick(e);
        }
    }

    もしくは、BindengNavigaterのOnItemClickedをオーバーライドしても良いと思います。
    OnItemClickedではどのボタンが押されたのかわかりますので、そこでエラーチェックをして、問題がなければBase.OnItemClicked(e)、問題があればthis.BindingSource.CancelEdit()を実行すれば良いのではないでしょうか?(すみません。未検証です)


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク 星 睦美 2014年4月22日 5:12
    2014年4月21日 2:25
    モデレータ
  • ToolStripButton の Click イベントのハンドラで処置できませんか? 以下のような感じです。

    注意:昔作ったソースをそのまま貼り付けました。なので、あくまで「感じ」です。ご自分のケースに合わせて検討ください(catch するのが Exception でいいのかなど)。

            // 最初に移動ボタン(パスデータ)
            private void pathMoveFirst_Click(object sender, EventArgs e)
            {
                try
                {
                    pathBindingSource.MoveFirst();
    
                    // これがクリック可能なら Count は2以上
                    pathMoveFirst.Enabled = false;
                    pathMovePrevious.Enabled = false;
                    pathMoveNext.Enabled = true;
                    pathMoveLast.Enabled = true;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n\nデータを修正するか終了してください。",
                        "「最初に移動」ボタン操作エラー(パスデータ)",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
    
            // 前に戻るボタン(パスデータ)
            private void pathMovePrevious_Click(object sender, EventArgs e)
            {
                try
                {
                    pathBindingSource.MovePrevious();
                    
                    pathMoveNext.Enabled = true;
                    pathMoveLast.Enabled = true;
                    if (pathBindingSource.Position == 0)
                    {
                        pathMoveFirst.Enabled = false;
                        pathMovePrevious.Enabled = false;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n\nデータを修正するか終了してください。",
                        "「前に戻る」ボタン操作エラー(パスデータ)",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
    
            // 次に移動ボタン(パスデータ)
            private void pathMoveNext_Click(object sender, EventArgs e)
            {
                try
                {
                    this.pathBindingSource.MoveNext();
    
                    pathMoveFirst.Enabled = true;
                    pathMovePrevious.Enabled = true;
                    if (pathBindingSource.Position == pathBindingSource.Count -1)
                    {
                        pathMoveNext.Enabled = false;
                        pathMoveLast.Enabled = false;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n\nデータを修正するか終了してください。",
                        "「次に移動」ボタン操作エラー(パスデータ)",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
    
            // 最後に移動ボタン(パスデータ)
            private void pathMoveLast_Click(object sender, EventArgs e)
            {
                try
                {
                    this.pathBindingSource.MoveLast();
    
                    pathMoveFirst.Enabled = true;
                    pathMovePrevious.Enabled = true;
                    pathMoveNext.Enabled = false;
                    pathMoveLast.Enabled = false;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n\nデータを修正するか終了してください。",
                        "「最後に移動」ボタン操作エラー(パスデータ)",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
    
            // 新規追加ボタン(パスデータ)
            private void pathAddNew_Click(object sender, EventArgs e)
            {
                try
                {
                    this.pathBindingSource.AddNew();
    
                    int count = pathBindingSource.Count;
                    if (count == 1)
                    {
                        pathDelete.Enabled = true;
                    }
                    else
                    {
                        pathMoveFirst.Enabled = true;
                        pathMovePrevious.Enabled = true;
                        pathMoveNext.Enabled = false;
                        pathMoveLast.Enabled = false;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n\nデータを修正するか終了してください。",
                        "「新規追加」ボタン操作エラー(パスデータ)",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
            
            // 削除ボタン(パスデータ)
            private void pathDelete_Click(object sender, EventArgs e)
            {
                this.pathBindingSource.RemoveCurrent();
    
                int count = pathBindingSource.Count;
    
                // 途中から消していった場合これが必要
                if (pathBindingSource.Position == count - 1)
                {
                    pathMoveNext.Enabled = false;
                    pathMoveLast.Enabled = false;
                }
    
                if (count <= 1)
                {
                    pathMoveFirst.Enabled = false;
                    pathMovePrevious.Enabled = false;
                    pathMoveNext.Enabled = false;
                    pathMoveLast.Enabled = false;
                }
                
                if (count == 0)
                    pathDelete.Enabled = false;
            }

    • 回答としてマーク 星 睦美 2014年4月22日 5:12
    2014年4月21日 3:54

すべての返信

  • これはおそらく昔からよく言われている、削除ボタンを押した時に削除の確認をしたいという質問と同じ種類のものだと思います。
    BindingNavigatorのこれらのボタンはToolStripItemです。ですから、このOnClickメソッドをオーバーライドしたものを、BindingNavigatorの例えばMoveNextItemプロパティにセットしてやれば良いように思います。例えば以下のような感じです。

    partial class CustomToolStripButton : System.Windows.Forms.ToolStripButton
    {
        protected override void OnClick(EventArgs e)
        {
            //エラーチェックして、問題なければbase.OnClick(e)を実行      
    
            base.OnClick(e);
        }
    }

    もしくは、BindengNavigaterのOnItemClickedをオーバーライドしても良いと思います。
    OnItemClickedではどのボタンが押されたのかわかりますので、そこでエラーチェックをして、問題がなければBase.OnItemClicked(e)、問題があればthis.BindingSource.CancelEdit()を実行すれば良いのではないでしょうか?(すみません。未検証です)


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク 星 睦美 2014年4月22日 5:12
    2014年4月21日 2:25
    モデレータ
  • ToolStripButton の Click イベントのハンドラで処置できませんか? 以下のような感じです。

    注意:昔作ったソースをそのまま貼り付けました。なので、あくまで「感じ」です。ご自分のケースに合わせて検討ください(catch するのが Exception でいいのかなど)。

            // 最初に移動ボタン(パスデータ)
            private void pathMoveFirst_Click(object sender, EventArgs e)
            {
                try
                {
                    pathBindingSource.MoveFirst();
    
                    // これがクリック可能なら Count は2以上
                    pathMoveFirst.Enabled = false;
                    pathMovePrevious.Enabled = false;
                    pathMoveNext.Enabled = true;
                    pathMoveLast.Enabled = true;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n\nデータを修正するか終了してください。",
                        "「最初に移動」ボタン操作エラー(パスデータ)",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
    
            // 前に戻るボタン(パスデータ)
            private void pathMovePrevious_Click(object sender, EventArgs e)
            {
                try
                {
                    pathBindingSource.MovePrevious();
                    
                    pathMoveNext.Enabled = true;
                    pathMoveLast.Enabled = true;
                    if (pathBindingSource.Position == 0)
                    {
                        pathMoveFirst.Enabled = false;
                        pathMovePrevious.Enabled = false;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n\nデータを修正するか終了してください。",
                        "「前に戻る」ボタン操作エラー(パスデータ)",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
    
            // 次に移動ボタン(パスデータ)
            private void pathMoveNext_Click(object sender, EventArgs e)
            {
                try
                {
                    this.pathBindingSource.MoveNext();
    
                    pathMoveFirst.Enabled = true;
                    pathMovePrevious.Enabled = true;
                    if (pathBindingSource.Position == pathBindingSource.Count -1)
                    {
                        pathMoveNext.Enabled = false;
                        pathMoveLast.Enabled = false;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n\nデータを修正するか終了してください。",
                        "「次に移動」ボタン操作エラー(パスデータ)",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
    
            // 最後に移動ボタン(パスデータ)
            private void pathMoveLast_Click(object sender, EventArgs e)
            {
                try
                {
                    this.pathBindingSource.MoveLast();
    
                    pathMoveFirst.Enabled = true;
                    pathMovePrevious.Enabled = true;
                    pathMoveNext.Enabled = false;
                    pathMoveLast.Enabled = false;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n\nデータを修正するか終了してください。",
                        "「最後に移動」ボタン操作エラー(パスデータ)",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
    
            // 新規追加ボタン(パスデータ)
            private void pathAddNew_Click(object sender, EventArgs e)
            {
                try
                {
                    this.pathBindingSource.AddNew();
    
                    int count = pathBindingSource.Count;
                    if (count == 1)
                    {
                        pathDelete.Enabled = true;
                    }
                    else
                    {
                        pathMoveFirst.Enabled = true;
                        pathMovePrevious.Enabled = true;
                        pathMoveNext.Enabled = false;
                        pathMoveLast.Enabled = false;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message + "\n\nデータを修正するか終了してください。",
                        "「新規追加」ボタン操作エラー(パスデータ)",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
            
            // 削除ボタン(パスデータ)
            private void pathDelete_Click(object sender, EventArgs e)
            {
                this.pathBindingSource.RemoveCurrent();
    
                int count = pathBindingSource.Count;
    
                // 途中から消していった場合これが必要
                if (pathBindingSource.Position == count - 1)
                {
                    pathMoveNext.Enabled = false;
                    pathMoveLast.Enabled = false;
                }
    
                if (count <= 1)
                {
                    pathMoveFirst.Enabled = false;
                    pathMovePrevious.Enabled = false;
                    pathMoveNext.Enabled = false;
                    pathMoveLast.Enabled = false;
                }
                
                if (count == 0)
                    pathDelete.Enabled = false;
            }

    • 回答としてマーク 星 睦美 2014年4月22日 5:12
    2014年4月21日 3:54
  • ありがとうございます。

    試してみたのですが、オーバーライドしてチェックしようとしましたが、先に

    NoNullAllowedExceptionエラーがprogram.csで発生し、チェック処理する前に

    中断してしまいます。

    BindengNavigaterを使用せずにコントローールを自作してやってみます。

    2014年4月21日 13:53
  • 丁寧なご回答ありがとうございました。

    提供していただいたサンプルを利用してやってみます。

    2014年4月21日 13:55
  • 一つ二つ忘れていました。

    Visual Studio のウィザードで DataSource ウィンドウから Form にドラッグ&ドロップしてコードを自動生成させると、BindingNavigator の AddNewItem, DeleteItem, MoveFirstItem, MoveLastItem, MoveNextItem, MovePreviousItem プロパティに ToolStripButton への参照が設定されるはずですが、これを null にしないとダメなので注意してください。

    具体的なやりかたは、Form2.Designer.cs のコードをいじるのではなく、Form2.cs [デザイン] 画面で BindingNavigator を選択し、プロパティウィンドウ上で AddNewItem, DeleteItem, MoveFirstItem, MoveLastItem, MoveNextItem, MovePreviousItem プロパティを (なし) に設定してください。

    さらに、Form2_Load で Fill した後あたりで、初期表示の設定をしてください。以下のような感じです(これもあくまで【感じ】です)。

                int count = pathBindingSource.Count;
                int position = pathBindingSource.Position;
                if (count <= 1)
                {
                    pathMoveFirst.Enabled = false;
                    pathMovePrevious.Enabled = false;
                    pathMoveNext.Enabled = false;
                    pathMoveLast.Enabled = false;
                    if (count == 0)
                        pathDelete.Enabled = false;
                }
                
                if (position == 0)
                {
                    pathMoveFirst.Enabled = false;
                    pathMovePrevious.Enabled = false;
                }
                
                if (position == count - 1)
                {
                    pathMoveNext.Enabled = false;
                    pathMoveLast.Enabled = false;
                }


    • 編集済み SurferOnWww 2014年4月22日 5:37 誤記訂正
    2014年4月22日 5:24
  • ご丁寧にありがとうございます。

    助かります。

    なんかいい感じです。

    2014年4月22日 14:21