Search code examples
c#winformsdatagridviewrowright-click

Create Right Click Menu on dataGridView for entire row


I have a simple dataGridView filled with stuff, now I want to be able to right-click the left side to highlight the entire row so I can insert or delete entire row. I've been searching for this for a while, but most of the time it's for single cells, I'm looking for a context menu that is used on entire rows.

There is another question that is similar but ultimately not exactly what I'm trying to do.

Thank you in advance!!


Solution

  • I found a pretty easy way to do what I wanted to do. It goes like this:

    first of all, hook up a mouseDown event:

    dataGridView1.MouseDown += new MouseEventHandler(this.dataGridView1_MouseClick);
    

    then, create the routine co-responding to the mouseDown event..

     private void dataGridView1_MouseClick(Object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                ContextMenu cm = new ContextMenu();
                this.ContextMenu = cm;
                cm.MenuItems.Add(new MenuItem("&Cut", new System.EventHandler(this.cut_Click)));
                cm.MenuItems.Add(new MenuItem("&Copy", new System.EventHandler(this.copy2_Click)));
                cm.MenuItems.Add(new MenuItem("&Paste", new System.EventHandler(this.paste2_Click)));
    
    
    
                cm.Show(this, new Point(e.X, e.Y));
            }
    
        }
    

    Then add your event routines, such as:

    private void cut_Click(Object sender, EventArgs e)
        {
            if (this.dataGridView1.GetCellCount(DataGridViewElementStates.Selected) > 0)
            {
                try
                {
                    Clipboard.SetDataObject(this.dataGridView1.GetClipboardContent());
                }
                catch (System.Runtime.InteropServices.ExternalException)
                {
                    MessageBox.Show("Clipboard could not be accessed. Please try again.");
                }
            }
    
            if (this.dataGridView1.SelectedRows.Count > 0)
            {
                dataGridView1.Rows.RemoveAt(this.dataGridView1.SelectedRows[0].Index);
            }
    
        }
    

    which will add the copied cells to the clip board. Then to paste them, something like:

    private void paste2_Click(Object sender, EventArgs e)
        {
            char[] rowSplitter = { '\r', '\n' };
            char[] columnSplitter = { '\t' };
    
            // Get the text from clipboard
            IDataObject dataInClipboard = Clipboard.GetDataObject();
            string stringInClipboard = (string)dataInClipboard.GetData(DataFormats.Text);
    
            // Split it into lines
            string[] rowsInClipboard = stringInClipboard.Split(rowSplitter, StringSplitOptions.RemoveEmptyEntries);
    
            // Get the row and column of selected cell in grid
            int r = dataGridView1.SelectedCells[0].RowIndex;
            int c = dataGridView1.SelectedCells[0].ColumnIndex;
    
            // Add rows into grid to fit clipboard lines
            if (dataGridView1.Rows.Count < (r + rowsInClipboard.Length))
            {
                dataGridView1.Rows.Add(r + rowsInClipboard.Length - dataGridView1.Rows.Count);
            }
    
            // Loop through the lines, split them into cells and place the values in the corresponding cell.
            for (int iRow = 0; iRow < rowsInClipboard.Length; iRow++)
            {
                // Split row into cell values
                string[] valuesInRow = rowsInClipboard[iRow].Split(columnSplitter);
    
                // Cycle through cell values
                for (int iCol = 0; iCol < valuesInRow.Length; iCol++)
                {
    
                    // Assign cell value, only if it within columns of the grid
                    if (dataGridView1.ColumnCount - 1 >= c + iCol)
                    {
                        DataGridViewCell cell = dataGridView1.Rows[r + iRow].Cells[c + iCol];
    
                        if (!cell.ReadOnly)
                        {
                            cell.Value = valuesInRow[iCol+1];
                        }
                    }
                }
            }
        }
    

    I use [col+1] because the first item in the list is always a blank (""). Hope this helps someone. It works for me! :D