Right Click Context Menu for Datagridview

Create Right Click Menu on dataGridView for entire row

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

How to get a contextmenu to appear on right click of a datagridview cell

try this code :

[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Drawing”)
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(1040,518)
$form.KeyPreview = $true
$form.StartPosition = 'centerscreen'
$form.BackColor = 'MidnightBlue'
$form.Add_KeyDown({if($_.KeyCode -eq "Escape"){$form.Close()}})
$form.Text = "VIOC Toolkit 5.4"
$form.Icon = [system.drawing.icon]::ExtractAssociatedIcon($PSHOME + "\powershell_ise.exe")
$form.MinimumSize = New-Object System.Drawing.Size(1040,525)

[System.Windows.Forms.DataGridView] $DataGrid1 = New-Object System.Windows.Forms.DataGridView
$DataGrid1.Location = New-Object System.Drawing.Size(298,29)
$DataGrid1.Dock = "Fill"
$DataGrid1.BorderStyle = 'FixedSingle'
#$DataGrid1.DefaultCellStyle.Font = New-Object System.Drawing.Font $dgfont,$dgfontSize
$DataGrid1.AlternatingRowsDefaultCellStyle.BackColor = 'LightGray'
$DataGrid1.AllowUserToAddRows = $false
$DataGrid1.RowHeadersVisible = $false
$DataGrid1.BackgroundColor = "White"
$DataGrid1.Name="DataGrid1"
$DataGrid1.Text="DataGrid1"
$DataGrid1.ColumnCount = 3
$DataGrid1.Columns[0].Name = 'one'
$DataGrid1.Columns[1].Name = 'two'
$DataGrid1.Columns[2].Name = 'three'
$DataGrid1.Rows.add(@('a', 'b', 'c'))
$DataGrid1.Rows.add(@('d', 'e', 'f'))

#Creation of content click event
$ClickElementMenu=
{
[System.Windows.Forms.ToolStripItem]$sender = $args[0]
[System.EventArgs]$e= $args[1]

$Contentcell=$DataGrid1.Rows[$DataGrid1.CurrentCell.RowIndex].Cells[$DataGrid1.CurrentCell.ColumnIndex].Value
$ElementMenuClicked=$sender.Text
$RowIndex=$DataGrid1.CurrentCell.RowIndex
$ColIndex=$DataGrid1.CurrentCell.ColumnIndex

$result="Click on element menu : '{0}' , in rowindex : {1} , column : {2}, content cell : {3}" -f $ElementMenuClicked, $RowIndex, $ColIndex, $Contentcell;
Write-Host $result
}

#creation menu
$contextMenuStrip1=New-Object System.Windows.Forms.ContextMenuStrip

#creation element1 of menu
[System.Windows.Forms.ToolStripItem]$toolStripItem1 = New-Object System.Windows.Forms.ToolStripMenuItem
$toolStripItem1.Text = "Element 1";
$toolStripItem1.add_Click($ClickElementMenu)
$contextMenuStrip1.Items.Add($toolStripItem1);

#creation element2 of menu
[System.Windows.Forms.ToolStripItem]$toolStripItem2 = New-Object System.Windows.Forms.ToolStripMenuItem
$toolStripItem2.Text = "Element 2";
$toolStripItem2.add_Click($ClickElementMenu)
$contextMenuStrip1.Items.Add($toolStripItem2);

#creation event of mouse down on datagrid and show menu when click
$DataGrid1.add_MouseDown({
$sender = $args[0]
[System.Windows.Forms.MouseEventArgs]$e= $args[1]

if ($e.Button -eq [System.Windows.Forms.MouseButtons]::Right)
{
[System.Windows.Forms.DataGridView+HitTestInfo] $hit = $DataGrid1.HitTest($e.X, $e.Y);
if ($hit.Type -eq [System.Windows.Forms.DataGridViewHitTestType]::Cell)
{
$DataGrid1.CurrentCell = $DataGrid1[$hit.ColumnIndex, $hit.RowIndex];
$contextMenuStrip1.Show($DataGrid1, $e.X, $e.Y);
}

}
})

#***************************************************************#
$form.Controls.Add($DataGrid1)
$form.ShowDialog() | out-null

Context menu not displaying near datagridview cell where right click occurred

Getting the context menu to display next to the last “selected” cell is doable; however, it is not going to be very user friendly. In most cases, when a user “right-clicks” on something a context menu is expected to appear “underneath” wherever the mouse “pointer” was when the user “right-clicked”. What you are describing is moving the context menu “away” from where the mouse “arrow” is located. I am confident most users will not be expecting this.

I am guessing from what you posted… that the user selects multiple cells in the grid, then the user “right-clicks” somewhere on the grid. This would display a context menu (underneath the MOUSE and not move the menu to some selected cell). The context menu would display the “OffLine/OnLine” menu items. Then after the user selects “Online/Offline”, some method would use the “selected” cells in the grid as data to set the cells online or offline. This is about as much as I can decipher from your question.

To help, below are some suggestions. The last line of code in the post….

m.Show(machineGrid, new Point(e.X, e.Y));

The above line moves the context menu to the grids X, Y values using the UI coordinates. This appears to have nothing to do with which cells are “selected”. Yet this will move the context menu somewhere above where the user right clicked... forcing the user to “chase” the context menu.

Lastly, I question the use of the “CellMouseDown” event to do this context menu logic. The DataGridView has its own “ContextMenuStrip” which you can set. Using the DataGridView’s ContextMenuStrip may be an easier approach. Below is an example of setting a DataGridView named dgv_PlayerPool with a ContextMenuStrip as described.

private void SetContexMenu() {
ContextMenuStrip cms = new ContextMenuStrip();
cms.Items.Add("Set OnLine", null, setOnline_Click);
cms.Items.Add("Set OffLine", null, setOffline_Click);
dgv_PlayerPool.ContextMenuStrip = cms;
}

The items add line above, takes a string to display in the menu, an image and finally an event to call when clicked.

The events fired when the user selects a context menu item.

private void setOffline_Click(object sender, EventArgs e) {
MessageBox.Show("SetOffLine");
}
private void setOnline_Click(object sender, EventArgs e) {
MessageBox.Show("SetOnLine");
}

Hope this makes sense.

Right click to select a row in a Datagridview and show a menu to delete it

I finally solved it:

  • In Visual Studio, create a ContextMenuStrip with an item called "DeleteRow"

  • Then at the DataGridView link the ContextMenuStrip

Using the code below helped me getting it work.

this.MyDataGridView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MyDataGridView_MouseDown);
this.DeleteRow.Click += new System.EventHandler(this.DeleteRow_Click);

Here is the cool part

private void MyDataGridView_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Right)
{
var hti = MyDataGridView.HitTest(e.X, e.Y);
MyDataGridView.ClearSelection();
MyDataGridView.Rows[hti.RowIndex].Selected = true;
}
}

private void DeleteRow_Click(object sender, EventArgs e)
{
Int32 rowToDelete = MyDataGridView.Rows.GetFirstRow(DataGridViewElementStates.Selected);
MyDataGridView.Rows.RemoveAt(rowToDelete);
MyDataGridView.ClearSelection();
}

Opening a context menu on DataGridView

The context menu will popup before the CellMouseClick event is fired so move your code to CellMouseDown instead.

Private Sub DataGridView1_CellMouseDown(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.CellMouseDown
If e.Button = Windows.Forms.MouseButtons.Right Then
If e.ColumnIndex <> -1 And e.RowIndex <> -1 Then
Me.DataGridView1.ClearSelection()
Dim cell = Me.DataGridView1.Item(e.ColumnIndex, e.RowIndex)
Me.DataGridView1.CurrentCell = cell
cell.Selected = True 'Needed if you right click twice on the same cell
DataGridView1.ContextMenuStrip = mnuCell
End If
End If
End Sub

C# DataGridView opening ContextMenu at location of Right Click

Option 1: The most simple solution for showing a context menu for rows is assigning the context menu to RowTemplate.ContextMenuStrip property of DataGridView:

dataGridView1.RowTemplate.ContextMenuStrip = contextMenuStrip1;

Option 2: Also if you want to select the cell before showing the ContextMenuStrip, it's enough to handle CellContextMenuStripNeeded event:

private void dataGridView1_CellContextMenuStripNeeded(object sender,
DataGridViewCellContextMenuStripNeededEventArgs e)
{
if (e.RowIndex > -1 && e.ColumnIndex > -1)
{
dataGridView1.CurrentCell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
e.ContextMenuStrip = contextMenuStrip1;
}
}

What was your mistake?

You are calculating the mouse position on the DataGridView in a wrong way. You are using PointToClient which means this.PointToClient, while you need to use the method of DataGridView, for example dataGridView1.PointToClient:

myContextMenu.Show(dataGridView1,dataGridView1.PointToClient(Cursor.Position));

Just for your information you can simply show ContextMenu using this code and there is no need to use ContextMenuStrip.

But I strongly recommend you to use ContextMenuStrip.

C# DataGridView Right Click to ContextMenu Click Retrieve Cell Value

If you're going with the solution of that post, then note that he's subscribing to the CellMouseDown event, not the MouseDown event. This has a different signature.

Also, as of .Net 2.0, you don't need all the delegate wrapping syntax, you can just += the function that matches the signature of the event delegate, like so:

// Your updated MouseDown handler function with DataGridViewCellMouseEventArgs
GridView1.CellMouseDown += this.dataGridView_MouseDown;

Then you won't have the error message, and can do what you see in the post.

Right click to select row in DataGridView

Try setting the current cell like this (this will set the CurrentRow property of the DataGridView before the context menu item is selected):

    private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
var dataGrid = (DataGridView) sender;
if (e.Button == MouseButtons.Right && e.RowIndex != -1)
{
var row = dataGrid.Rows[e.RowIndex];
dataGrid.CurrentCell = row.Cells[e.ColumnIndex == -1 ? 1 : e.ColumnIndex];
row.Selected = true;
dataGrid.Focus();
}
}

DataGridView right-click menu/copy example?

You can use ContextMenuStrip to accomplish this.
(Or ContextMenu for pre-VS2k5)

Excerpt from this article:

ContextMenuStrip mnu = new ContextMenuStrip();
ToolStripMenuItem mnuCopy = new ToolStripMenuItem("Copy");
ToolStripMenuItem mnuCut = new ToolStripMenuItem("Cut");
ToolStripMenuItem mnuPaste = new ToolStripMenuItem("Paste");
//Assign event handlers
mnuCopy.Click += new EventHandler(mnuCopy_Click);
mnuCut.Click += new EventHandler(mnuCut_Click);
mnuPaste.Click += new EventHandler(mnuPaste_Click);
//Add to main context menu
mnu.Items.AddRange(new ToolStripItem[] { mnuCopy, mnuCut, mnuPaste});
//Assign to datagridview
dataGridView1.ContextMenuStrip = mnu;

There is more information on the above link.



Related Topics



Leave a reply



Submit