none
DataGridViewが空の時bindingNavigatorの削除を実行すると「現在の項目がないため、一覧から現在の項目を削除できません」 RRS feed

  • 質問

  • いつもありがとうございます。非常に助かっています。

    さて、また、DataGridView関係ですが、

    DataGridViewが空の時bindingNavigatorの削除を実行すると

    「現在の項目がないため、一覧から現在の項目を削除できません」の下記Exceptionが発生します。

    System.InvalidOperationException はハンドルされませんでした。
      Message=現在の項目がないため、一覧から現在の項目を削除できません。
      Source=System.Windows.Forms
      StackTrace:

    再現手順

    MS-ACCESSの簡単なmdbファイル(中身空っぽ)からデータセット、ドラッグアンドドロップでDataGridViewを貼りつけます。

    BindingNavigatorもフォーム上に自動で生成されます。これだけです。全くコーディングしていない状態です。

    この状態でいきなり「削除」ボタンを押下すると上記Exceptionが発生します。

    DeleteItemのClickイベントの前にExceptionが発生しているようです。

    (ブレークポイントをセットしても止まる前にExceptionが発生しています)

    どうにかしてExceptionを抑止あるいはハンドルして継続させたいのですが、

    どのように対処するのがいいでしょうか?お教えください。

    開発環境:

     Visual Studio 2010 Professional

    開発言語:

     C# 2010

    2015年11月13日 4:51

回答

  • そもそもBindingNavigatorは削除確認が出ないので、以下を参考にして削除確認を出した方が良いでしょう。

    Visual Studio 2005のフォームにおけるBindingNavigatorの拡張
    http://internetcom.jp/developer/20060627/26.html

    この削除確認のロジックでチェックし、削除対象の行が無ければ、そのようなメッセージを出せば良いように思います。


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答の候補に設定 星 睦美 2015年11月16日 4:47
    • 回答としてマーク 星 睦美 2015年12月22日 7:16
    2015年11月13日 7:43
    モデレータ
  • BindingNavigator が bindingNavigatorDeleteItem をコントロールしているらしく、たとえば Form1_Load メソッドで BindingSource.Count の値をしらべてゼロのとき Enabled を false にしても true に戻ってしまいます。

    なので bindingNavigatorDeleteItem を BindingNavigator のコントロール下から外してから Enabled を false にしないとダメなようです。

    しかし、コントロール下から外すと削除が効かなくなってしまうので、自力でコードを書いて bindingNavigatorDeleteItem のクリックイベントで削除できるようにしてやる必要があります。

    Enabled を true に戻す処置も必要になります。それは bindingNavigatorAddNewItem のクリックイベントでやるのがよさそうです。

    具体的には:

    (1) Visual Studio の Formx.cs [デザイン] 画面で BindingNavigator のプロパティを表示して、その中の AddNewItem と DeleteItem を (なし) に設定する。(Formx.Designer.cd のコードでは null になります・・・が、そちらを修正しないこと)

    (2) 既存の Form_Load メソッドに以下のようなコードを追加する。xXXBindingSource は自分のコードに合わせて修正してください。

    int count = this.xXXBindingSource.Count;
    if (count == 0)
    {
        this.bindingNavigatorDeleteItem.Enabled = false;
    }

    (3) bindingNavigatorDeleteItem と bindingNavigatorAddNewItem の Click イベントのハンドラを作る。

    (4) 上記 (3) で作ったハンドラに以下のようなコードを追加する。xXXBindingSource, xXXDataGridView は自分のコードに合わせて修正してください。

    private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
    {
        this.xXXBindingSource.RemoveCurrent();
    
        int count = this.xXXDataGridView.Rows.Count;
        if (count <= 1)
        {
            this.bindingNavigatorDeleteItem.Enabled = false;
        }
    }
    
    private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
    {
        this.xXXBindingSource.AddNew();
        this.bindingNavigatorDeleteItem.Enabled = true;
    }

    質問者さんのケースでうまく行くかどうか分かりませんが、試してみてください。
    • 回答の候補に設定 星 睦美 2015年11月16日 4:47
    • 回答としてマーク 星 睦美 2015年12月22日 7:16
    2015年11月13日 8:17

すべての返信

  • 自己レスです。

    BindingNavigatorのDeleteItemプロパティを(なし)にし、

    DataGridViewを継承したクラスを作り、protectedのProcessDeleteKeyを呼び出す(内部的にDelキーと同じ処理を行う)ようにクリックイベントをコーディングしたらExceptionは出なくなりました。


        class DataGridViewEx : DataGridView
        {
            public void Delete()
            {
                this.ProcessDeleteKey(Keys.Delete);
            }
        }
    

            private DataGridViewEx DataGridView1;
    
            this.DataGridView1 = new DataGridViewEx();
    
            ・・・
    
            private void bindingNavigatorDeleteItem1_Click(object sender, EventArgs e)
            {
                DataGridView1.Delete();
            }
    

    参考:フォーラムの「RowValidated イベントハンドラをもつ DataGridView で行を削除するには」

    2015年11月13日 5:50
  • そもそもBindingNavigatorは削除確認が出ないので、以下を参考にして削除確認を出した方が良いでしょう。

    Visual Studio 2005のフォームにおけるBindingNavigatorの拡張
    http://internetcom.jp/developer/20060627/26.html

    この削除確認のロジックでチェックし、削除対象の行が無ければ、そのようなメッセージを出せば良いように思います。


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答の候補に設定 星 睦美 2015年11月16日 4:47
    • 回答としてマーク 星 睦美 2015年12月22日 7:16
    2015年11月13日 7:43
    モデレータ
  • BindingNavigator が bindingNavigatorDeleteItem をコントロールしているらしく、たとえば Form1_Load メソッドで BindingSource.Count の値をしらべてゼロのとき Enabled を false にしても true に戻ってしまいます。

    なので bindingNavigatorDeleteItem を BindingNavigator のコントロール下から外してから Enabled を false にしないとダメなようです。

    しかし、コントロール下から外すと削除が効かなくなってしまうので、自力でコードを書いて bindingNavigatorDeleteItem のクリックイベントで削除できるようにしてやる必要があります。

    Enabled を true に戻す処置も必要になります。それは bindingNavigatorAddNewItem のクリックイベントでやるのがよさそうです。

    具体的には:

    (1) Visual Studio の Formx.cs [デザイン] 画面で BindingNavigator のプロパティを表示して、その中の AddNewItem と DeleteItem を (なし) に設定する。(Formx.Designer.cd のコードでは null になります・・・が、そちらを修正しないこと)

    (2) 既存の Form_Load メソッドに以下のようなコードを追加する。xXXBindingSource は自分のコードに合わせて修正してください。

    int count = this.xXXBindingSource.Count;
    if (count == 0)
    {
        this.bindingNavigatorDeleteItem.Enabled = false;
    }

    (3) bindingNavigatorDeleteItem と bindingNavigatorAddNewItem の Click イベントのハンドラを作る。

    (4) 上記 (3) で作ったハンドラに以下のようなコードを追加する。xXXBindingSource, xXXDataGridView は自分のコードに合わせて修正してください。

    private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
    {
        this.xXXBindingSource.RemoveCurrent();
    
        int count = this.xXXDataGridView.Rows.Count;
        if (count <= 1)
        {
            this.bindingNavigatorDeleteItem.Enabled = false;
        }
    }
    
    private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
    {
        this.xXXBindingSource.AddNew();
        this.bindingNavigatorDeleteItem.Enabled = true;
    }

    質問者さんのケースでうまく行くかどうか分かりませんが、試してみてください。
    • 回答の候補に設定 星 睦美 2015年11月16日 4:47
    • 回答としてマーク 星 睦美 2015年12月22日 7:16
    2015年11月13日 8:17