In my project I give user opportunity to add or remove a column of a DataGridView.
I do not know at runtime how many columns there might be, so in order to remove it or add one at index n , I need to know the column index clicked.

So my event handler knows that information, but a standard contextmenuitenclicked event does not.
I get around this by using a private member to keep track of the clicked column in my dataGridView1_ColumnHeaderMouseClick event handler shown in the below code.

My question is, is there a better way to do this?
Thank you for reading my post.

private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            clickedcolumn = e.ColumnIndex + 1;
            Point p = new Point(e.X, e.Y);
            ContextMenu cm = new ContextMenu();
            cm.MenuItems.Add("Remove column " + clickedcolumn.ToString(), removeToolStripMenuItem_Click);
            cm.MenuItems.Add("Add column " + clickedcolumn.ToString(), addToolStripMenuItem_Click);
            cm.Show(dataGridView1, p);
        }

        private void removeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Debug.WriteLine("Remove " + clickedcolumn);
            clickedcolumn = -1;
        }

        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Debug.WriteLine("Add " + clickedcolumn);
            clickedcolumn = -1;
        }

Recommended Answers

All 2 Replies

I once removed columns in a DGV by clicking in one of the cells of the column instead of in the header. So I could do something like this in the remove click handler:
this.InputDGV.Columns.RemoveAt(this.InputDGV.CurrentCell.ColumnIndex);

commented: Simple and elegant solution +11

Here's another solution. It has some advantages:
- user can open context menu over any cell in DGV
- you get both column index and row index if you need to remove/add rows too

Context menu creation is inside button click handler but probably should be in the code which initializes DGV.

    private void button4_Click(object sender, EventArgs e)
    {
        ToolStripMenuItem newItem;

        // Create a context menu
        newItem = new ToolStripMenuItem();
        newItem.Text = "Remove";
        newItem.Name = "contextRemove";
        // contextMenuItem_Click handles menu click
        newItem.Click += new EventHandler(contextMenuItem_Click);
        contextMenuStrip1.Items.Add(newItem);

        newItem = new ToolStripMenuItem();
        newItem.Text = "Add";
        newItem.Name = "contextAdd";
        // contextMenuItem_Click handles menu click
        newItem.Click += new EventHandler(contextMenuItem_Click);
        contextMenuStrip1.Items.Add(newItem);

        // Attach context menu to the DGV
        dataGridView1.ContextMenuStrip = contextMenuStrip1;
        // Add handler to capture context menu opening
        dataGridView1.MouseDown += new MouseEventHandler(dataGridView1_MouseDown);
    }

    // Global variable to hold mouse position coordinates
    internal Point contextMenuClickPosition;

    private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
    {
        // Context menu opens with right mouse button
        if (e.Button == System.Windows.Forms.MouseButtons.Right)
        {
            // User opened context menu, save this (x,y) position
            contextMenuClickPosition = e.Location;
        }   
    }

    private void contextMenuItem_Click(object sender, EventArgs e)
    {
        DataGridView.HitTestInfo hitPosition;
        Point cellIndex;

        // User has opened context menu. Use DGV's HitTest method to find 
        // the cell where user opened menu i.e. row index and column index.
        // Here the saved mouse coordinates are needed
        hitPosition = dataGridView1.HitTest(contextMenuClickPosition.X, contextMenuClickPosition.Y);
        // User has to open context menu over a cell
        if (hitPosition.Type == DataGridViewHitTestType.Cell)
        {
            // Now we know row and column indices
            // Notice that indices are zero-based
            cellIndex = new Point(hitPosition.RowIndex, hitPosition.ColumnIndex);
            // This just shows the cell coordinates
            MessageBox.Show("(Row,Col)=(" + cellIndex.X + "," + cellIndex.Y + ")");
        }
    }

HTH

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.