Search code examples
c#vb.netwinformsdatagridviewdatagridviewcolumn

Datagridview: Get column name by right clicking on column header (read info)


I have two datagridviews, and they both share the same datasource. I have chosen to only show the first n columns on my first dgv, and the rest n columns of my datasource on the second dgv like this:

for (int i = 0; i < mytable.Columns.Count; i++)
        {
            dataGridView1.Columns[i].Visible = i < n;
            dataGridView2.Columns[i].Visible = i >= n;
        }

Introduction: I want to right click and move columns from one datagridview to another at will. I do this by making the respective columns visible and not visible, since both datagridviews share the same datasource. I have run into problems concerning column indices of course.

Consider this example: I have a datatable of 5 columns, and I give that datasource to both my datagridviews. I decide to make the first 3 columns of the datatable visible on the first datagridvew, and the two remaining columns visible on the second. Now, if I wanted to move a column from the second datagridview to the first, I would first fire this event:

private void dataGridView2_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Right)
        {
            var ht = dataGridView1.HitTest(e.X, e.Y);
            currentColumnIndex = ht.ColumnIndex;

            if ((ht.Type == DataGridViewHitTestType.ColumnHeader))
            {

                contextMenuStrip2.Show(MousePosition);
            }
        }
    }

I have made it so that this will only show the context menu if the user has right clicked on a column header. Then, throught the contextmenu this happens:

 private void moveToFirstGridToolStripMenuItem_Click(object sender, EventArgs e)
    {
        dataGridView2.Columns[currentColumnIndex+dataGridView1.Columns.GetColumnCount(DataGridViewElementStates.Visible)].Visible = false;
        dataGridView1.Columns[currentColumnIndex + dataGridView1.Columns.GetColumnCount(DataGridViewElementStates.Visible)].Visible = true;
        currentColumnIndex = -5;
    }

currentColumnIndex is a global variable which was to track the index of the column the user right clicked on.

Problem: The problem is that this currentColumnIndex gets the index of the current datagridview's index, and not the whole dataset. In my example, if I go to the second dgv and right click the header of the second column, currentColumnIndex shows 1 instead of 4, which would be the correct global index. This leads to problems later on, when you for example move the second column first, and then the first one.

I believe it is important to have a way to know the correct global index of my columns. I wasn't sure whether this can be achieved, so I thought that maybe I could look for column names, since all the column names of my dataset will be unique. The question then is how to get the header column text when you right click on it, given the structure I have.

The question could have been much shorter, just including the last sentence of the last paragraph, but I wanted to give more accurate view of what is going on.


Solution

  • Answering my question: This will just solve the problem I described I had currently. It doesn't actually answer the question at the top. which is how to find the column name by right clicking. However it shouldn't be a problem getting the name and column info that you need when you actually have the correct index: dataGridView1.Columns[i]...

    Solution of my problem:

    It seems I don't need to look for a way of detecting the column names. Instead of using the DataGridViewi_MouseDown events, I now use the dataGridViewi_ColumnHeaderMouseClick which uses the DataGridViewCellMouseEventArgs class. So I moved the code from the former event to the latter. Now, whenever you use e.ColumnIndex, you actually get the correct index, meaning the index of the whole datatable and not just the current datagridview's index.

    To make this work I also change the code for making columns visible. Now it's just:

    private void moveToFirstGridToolStripMenuItem_Click(object sender, EventArgs e)
        {
            dataGridView2.Columns[currentColumnIndex].Visible = false;
            dataGridView1.Columns[currentColumnIndex].Visible = true;
            currentColumnIndex = -5;
        }