简体   繁体   English

如何在MouseUp事件而不是MouseDown事件中获取DataGridView列的索引?

[英]How to get a DataGridView column's index in a MouseUp event, not in a MouseDown event?

I have a WinForm with DataGridView , my goal is to drag one column and drop it on other column index. 我有一个带有DataGridView的WinForm,我的目标是将一个列拖放到另一列索引上。 I know column reordering is possible by using AllowUserToOrderColumns = true . 我知道可以通过使用AllowUserToOrderColumns = true来对列进行重新排序。 But I have to perform other operations on DGV. 但是我必须对DGV执行其他操作。 That's why I need the target column index at a mouse-up event. 这就是为什么在鼠标向上移动事件时需要目标列索引的原因。 To do that, I use HitTestInfo : 为此,我使用HitTestInfo

System.Windows.Forms.DataGrid.HitTestInfo myHitTest;
myHitTest = dataGrid1.HitTest(e.X, e.Y);
int p = myHitTest.ColumnIndex;

When I click on the first DGV column, this code runs and gives me the column's index ( p ). 当我单击第一个DGV列时,此代码将运行并为我提供该列的索引( p )。 The problem is when I drop it on the other column of DGV, I'd like to know the target column's index, with the same code p = -1 , I think because the HitTestInfo member returns a value on a MouseDown and not on a MouseUp . 问题是,当我将其放在DGV的另一列时,我想知道目标列的索引,使用相同的代码p = -1 ,我想是因为HitTestInfo成员在MouseDown不是 a上返回值MouseUp If anyone can tell me how to do it, it would be very great. 如果有人可以告诉我该怎么做,那就太好了。

You can create two HitTestInfo objects, one in the MouseDown and one in the MouseUp . 您可以创建两个HitTestInfo对象,一个在MouseDown ,一个在MouseUp

IMO, you also should use the DataGridView.HitTestInfo class, not DataGrid.HitTestInfo and try to not call or name DataGridViews DataGrids , which is a similar but different Control from WPF ! 海事组织,你也应该使用DataGridView.HitTestInfo类,而不是DataGrid.HitTestInfo并尽量不叫或名称DataGridViews DataGrids ,这是从类似,但不同的控制WPF

DataGridView.HitTestInfo myHitTestDown, myHitTestUp;
int visibleColumnDown, visibleColumnUp;

private void dataGrid1_MouseUp(object sender, MouseEventArgs e)
{
    myHitTestUp = dataGrid1.HitTest(e.X, e.Y);
    visibleColumnUp = getVisibleColumn(dataGrid1, e.X);
}

private void dataGrid1_MouseDown(object sender, MouseEventArgs e)
{
    myHitTestDown = dataGrid1.HitTest(e.X, e.Y);
    visibleColumnDown = getVisibleColumn(dataGrid1, e.X);
}

Update: To find the visible index of a column after the columns have been reordered simply use: 更新:要在对列进行重新排序后查找列的可见索引,只需使用:

dataGrid1.Columns[myHitTestUp.ColumnIndex].DisplayIndex;

Before I found that, I wrote this little helper function, which does the same: 在发现之前,我写了这个小辅助函数,其功能相同:

int getVisibleColumn(DataGridView dgv, int x)
{
    int cx = dgv.RowHeadersWidth;
    int c = 0;
    foreach (DataGridViewColumn col in dgv.Columns)
    {
        cx += col.Width; if ( cx >= x) return c; c++;
    }
    return -1;
}

To find out which Column was shuffled seems to be a bit harder. 要找出洗牌的专栏似乎有点困难。 There is an event, which gets called for each column that was affected and it always gets called first for the one that was dragged along. 有一个事件,将为受影响的 每一列调用该事件,并且始终将其拖到最前面。 Here is one way to do it: 这是一种实现方法:

Create to variables at class level: 在类级别创建变量:

List<DataGridViewColumn> shuffled = new List<DataGridViewColumn>();
DataGridViewColumn shuffledColumn = null;

Remember the first column: 记住第一列:

private void dgvLoadTable_ColumnDisplayIndexChanged(
             object sender, DataGridViewColumnEventArgs e)
{
    if (shuffledColumn == null) shuffledColumn = e.Column;
}

Forget what happend before: 忘记之前发生的事情:

private void dgvLoadTable_MouseDown(object sender, MouseEventArgs e)
{  
    shuffledColumn = null;
}

Now you can use it. 现在您可以使用它了。 Selecting Columns is, however, not going well with shuffling them! 但是,选择列不能很好地进行改组! If you do 如果你这样做

 shuffledColumn.Selected = true;

it will only be selected if the SelectionMode is either FullColumnSelect or ColumnHeaderSelect - In either mode the shuffling will not work, I'm afraid.. 如果它只会被选中SelectionMode或者是FullColumnSelectColumnHeaderSelect -在这两种模式下,洗牌是行不通的,我怕..

You could use drag'n'drop for that. 您可以为此使用拖放。
Assume you have a Form with a DataGridView named dataGridView1 . 假设您有一个带有DataGridViewForm ,该Form名为dataGridView1

Initially don't forget to allow drag'n'drop for DataGridView : 最初,不要忘记为DataGridView拖放操作:

dataGridView1.AllowDrop = true;

The event handler which replaces the desired functionality of MouseUp would be the dataGridView1_DragDrop , and the target column's index is colIndexOfItemUnderMouseToDrop : 替换MouseUp所需功能的事件处理程序将是dataGridView1_DragDrop ,而目标列的索引是colIndexOfItemUnderMouseToDrop

private Rectangle dragBoxFromMouseDown;
private int colIndexFromMouseDown;

private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
    if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
    {
        // If the mouse moves outside the rectangle, start the drag.
        if (dragBoxFromMouseDown != Rectangle.Empty &&
            !dragBoxFromMouseDown.Contains(e.X, e.Y))
        {
            // Proceed with the drag and drop, passing in the list item.                    
            dataGridView1.DoDragDrop(colIndexFromMouseDown, DragDropEffects.Move);
        }
    }
}

private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
    // Get the index of the item the mouse is below.
    colIndexFromMouseDown = dataGridView1.HitTest(e.X, e.Y).ColumnIndex;

    if (colIndexFromMouseDown != -1)
    {
        // Remember the point where the mouse down occurred. 
        // The DragSize indicates the size that the mouse can move 
        // before a drag event should be started.                
        Size dragSize = SystemInformation.DragSize;

        // Create a rectangle using the DragSize, with the mouse position being
        // at the center of the rectangle.
        dragBoxFromMouseDown = new Rectangle(
            new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)),
            dragSize);
    }
    else
        // Reset the rectangle if the mouse is not over an item in the ListBox.
        dragBoxFromMouseDown = Rectangle.Empty;
}

private void dataGridView1_DragOver(object sender, DragEventArgs e)
{
    e.Effect = DragDropEffects.Move;
}

private void dataGridView1_DragDrop(object sender, DragEventArgs e)
{
    // If the drag operation was a move then remove and insert the column.
    if (e.Effect == DragDropEffects.Move)
    {
        // The mouse locations are relative to the screen, so they must be 
        // converted to client coordinates.
        Point clientPoint = dataGridView1.PointToClient(new Point(e.X, e.Y));

        // Get the column index of the item the mouse is below. 
        int colIndexOfItemUnderMouseToDrop = dataGridView1.HitTest(clientPoint.X, clientPoint.Y).ColumnIndex;
        if (colIndexOfItemUnderMouseToDrop == -1)
            return;
        colIndexOfItemUnderMouseToDrop = dataGridView1.Columns[colIndexOfItemUnderMouseToDrop].DisplayIndex;
        // Now we have the column's display index.

        if (e.Data.GetDataPresent(typeof(int)))
        {
            int colToMove = (int)e.Data.GetData(typeof(int));
            dataGridView1.Columns[colToMove].DisplayIndex = colIndexOfItemUnderMouseToDrop;
            // Select the column:
            dataGridView1.Columns[colToMove].Selected = true;
        }
    }
}

EDIT 编辑
New approach: 新的方法:

private DataGridViewColumn columnToMove;

public Form1()
{
    InitializeComponent();

    dataGridView1.Columns.AddRange(new DataGridViewColumn[]
        {
            new DataGridViewTextBoxColumn { Name = "AAA", SortMode = DataGridViewColumnSortMode.NotSortable },
            new DataGridViewTextBoxColumn { Name = "BBB", SortMode = DataGridViewColumnSortMode.NotSortable },
            new DataGridViewTextBoxColumn { Name = "CCC", SortMode = DataGridViewColumnSortMode.NotSortable }
        });
    dataGridView1.Rows.Add(2);
    dataGridView1.AllowUserToOrderColumns = true;
    dataGridView1.MouseDown += dataGridView1_MouseDown;
    dataGridView1.ColumnDisplayIndexChanged += dataGridView1_ColumnDisplayIndexChanged;
}

private void dataGridView1_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e)
{
    if (e.Column == columnToMove)
    {
        dataGridView1.SelectionMode = DataGridViewSelectionMode.ColumnHeaderSelect;
        e.Column.Selected = true;
    }
}

private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
{
    var hti = dataGridView1.HitTest(e.X, e.Y);
    if (hti.Type == DataGridViewHitTestType.ColumnHeader)
    {
        columnToMove = dataGridView1.Columns[hti.ColumnIndex];
        dataGridView1.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM