none
dataGridViewの行ヘッダー右クリックでメニューが出ないのはなぜ? RRS feed

  • 質問

  • 行を選択して行ヘッダーで右クリックしたとの「行削除」メニューの表示のことでお教え願います。

    下のコードでは,行を削除した後に再び行を削除しようとしたときには,<右クリックしてもメニューが表示されない>という不具合が生じていまいます。この不具合の原因と対処の仕方を知りたいと思います。どうぞよろしくお願いします。

    //-- 行ヘッダにContextMenuStrip1を関連付け  
    foreach (DataGridViewRow row in suitoDataGridView.Rows)
    {
      row.HeaderCell.ContextMenuStrip = contextMenuStrip1;
    }
    ////////////////////////////////////////////////////////////
    private void 行削除ToolStripMenuItem_Click(object sender, EventArgs e)
    {
      //削除するかどうか
      DialogResult dlgRet;
      dlgRet = MessageBox.Show("削除しますか?", "選択行削除",
        MessageBoxButtons.YesNo, MessageBoxIcon.Question);
      switch (dlgRet )
      {
        case DialogResult.Yes :
          //選択されているすべての行を削除する
          DataGridView dgv = (DataGridView)suitoDataGridView;
          int del = 0;
          foreach (DataGridViewRow r in dgv.SelectedRows)
          {
            if (!r.IsNewRow)
            {
              dgv.Rows.Remove(r);
              del++;
             }
           }
           this.Validate();
           this.groupSuitoBindingSource.EndEdit();
           this.groupSuitoTableAdapter.Update(this.suitoDataSet6.groupSuito);
           //削除結果
           MessageBox.Show(del.ToString() 
             + " 行のデータを\n削除しました。", "削除結果");
    
           suitoDataSet6.Clear();
           this.groupSuitoTableAdapter.Fill(this.suitoDataSet6.groupSuito);
           break;
         case DialogResult.No :
           break;
      }
    }
    

    zen73
    2010年8月16日 13:35

回答

  • 一度目はコンテキストメニューが表示されて削除することができ、二度目はコンテキストメニューが表示されないということでよろしいでしょうか? であれば、

    //-- 行ヘッダにContextMenuStrip1を関連付け 
    foreach (DataGridViewRow row in suitoDataGridView.Rows)
    {
      row.HeaderCell.ContextMenuStrip = contextMenuStrip1;
    }

    が二度目にうまく実行されていないのではないでしょうか?

    ところで、余計なお世話かもしれませんが、直感的には複数行を選択したのち、行のどの部分を右クリックしてもコンテキストメニューが出るようにした方が良いように思います。つまり、DataGridViewのContextMenuStripプロパティに contextMenuStrip1をセットします。先走ってしまいますが、参考として、右クリックで行を選択するには以下のようにします。趣旨に合わなければ流して下さい。

    private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
    {
      if (e.Button == MouseButtons.Right)  //左ボタンが押された時は、CTRLやSHIFTと組み合わせて、複数行を選択できるようにするため。
      {
        DataGridView.HitTestInfo hti = ((DataGridView)sender).HitTest(e.X, e.Y);
    
        if (hti.Type == DataGridViewHitTestType.Cell)
          ((DataGridView)sender).CurrentCell = ((DataGridView)sender)[hti.ColumnIndex, hti.RowIndex];
      }
    }
    

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク zen73 2010年8月16日 18:58
    2010年8月16日 15:21
    モデレータ

すべての返信

  • 一度目はコンテキストメニューが表示されて削除することができ、二度目はコンテキストメニューが表示されないということでよろしいでしょうか? であれば、

    //-- 行ヘッダにContextMenuStrip1を関連付け 
    foreach (DataGridViewRow row in suitoDataGridView.Rows)
    {
      row.HeaderCell.ContextMenuStrip = contextMenuStrip1;
    }

    が二度目にうまく実行されていないのではないでしょうか?

    ところで、余計なお世話かもしれませんが、直感的には複数行を選択したのち、行のどの部分を右クリックしてもコンテキストメニューが出るようにした方が良いように思います。つまり、DataGridViewのContextMenuStripプロパティに contextMenuStrip1をセットします。先走ってしまいますが、参考として、右クリックで行を選択するには以下のようにします。趣旨に合わなければ流して下さい。

    private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
    {
      if (e.Button == MouseButtons.Right)  //左ボタンが押された時は、CTRLやSHIFTと組み合わせて、複数行を選択できるようにするため。
      {
        DataGridView.HitTestInfo hti = ((DataGridView)sender).HitTest(e.X, e.Y);
    
        if (hti.Type == DataGridViewHitTestType.Cell)
          ((DataGridView)sender).CurrentCell = ((DataGridView)sender)[hti.ColumnIndex, hti.RowIndex];
      }
    }
    

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク zen73 2010年8月16日 18:58
    2010年8月16日 15:21
    モデレータ
  • >DataGridViewのContextMenuStripプロパティに contextMenuStrip1をセットします。

    これにより,不具合を解消できました。trapemiyaさん,ありがとうございました。

    >右クリックで行を選択するには以下のようにします。

    今回は見送ることとします。私には魔法に思えてしまいますが,なんでもできることに驚きました。

     


    zen73
    2010年8月16日 22:03
  • 解決済みですが、もうひとつの方法を書かせてもらいます。

    suitoDataGridView はバインドして使用されているのですよね?
    以下はその場合の話です。

    Cell のプロパティは、ListChangedType.Reset などの様々なタイミングで初期化されます。
    たとえば以下のようにすると、削除操作によって●が消えることを確認できると思います。
    (この動作はバインド時の仕様によるものだと思います。)

    foreach (DataGridViewRow row in suitoDataGridView.Rows)
    {
      row.HeaderCell.ContextMenuStrip = contextMenuStrip1;
      row.HeaderCell.Value = "●";
    }

    コンテキストメニューを任意のセルで表示する手段として、CellContextMenuStripNeeded イベントが用意されています。

    private void dataGridView1_CellContextMenuStripNeeded(
        object sender, DataGridViewCellContextMenuStripNeededEventArgs e)
    {
        // RowHeader の場合にメニューを表示します。
        if (e.ColumnIndex == -1 && e.RowIndex != -1)
            e.ContextMenuStrip = contextMenuStrip1;
    }

    2010年8月17日 6:35