2014-10-19 66 views
0

我有一個WinForm與DataGridView,我的目標是拖動一列,並將其放在其他列索引。我知道使用AllowUserToOrderColumns = true列重新排序是可能的。但是我必須在DGV上執行其他操作。這就是爲什麼我需要在鼠標事件時使用目標列索引。要做到這一點,我用HitTestInfo如何在MouseUp事件中獲取DataGridView列的索引,而不是在MouseDown事件中?

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

當我點擊第一列DGV,該代碼運行並給我列的索引(p)。問題是,當我把它放在DGV的另一列上時,我想知道目標列的索引,使用相同的代碼p = -1,我想這是因爲HitTestInfo成員返回MouseDown上的值而不是上的MouseUp 。如果有人能告訴我該怎麼做,那將非常棒。

+0

您可以通過添加一個MouseUp事件到設計器視圖>選擇yout dgv>轉到事件>並雙擊MouseUp – Sybren 2014-10-19 10:08:07

回答

0

您可以創建兩個HitTestInfo對象,一個在MouseDown中,另一個在MouseUp中。

IMO,你也應該使用DataGridView.HitTestInfo類,而不是DataGrid.HitTestInfo並儘量不叫或名稱DataGridViewsDataGrids,這是從一個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); 
} 

更新:要找到後列已重新排序,只需使用一列的可見指數:

dataGrid1.Columns[myHitTestUp.ColumnIndex].DisplayIndex; 

之前,我發現,我寫了這個小幫手功能,它執行相同:

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; 
} 

要找出哪個列被洗牌似乎有點困難。有一個事件,需要,每個列是受影響的,並且它總是首先被拖動。下面是做這件事:

創建在類級別的變量:

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

記住的第一列:

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

忘記發生了什麼之前:

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

現在你可以使用它。然而,選擇列與混洗它們並不合適!如果你

shuffledColumn.Selected = true; 

它只會被選中,如果SelectionMode或者是FullColumnSelectColumnHeaderSelect - 在這兩種模式下,洗牌是行不通的,我怕..

+0

它適用於拖ñ下拉菜單,但是當我連續重新洗滌同一列時,mouseup上的ColumnIndex會給出錯誤的索引位置,從而導致丟失。 – 2014-10-19 11:37:14

+0

啊,沒錯。沒有注意到洗牌,對不起。我爲我的答案添加了一個輔助函數。 – TaW 2014-10-19 12:14:28

+0

這對我來說非常有用。你能否提出一個代碼,在重新洗牌的時候,應該在鼠標事件中選擇洗牌的專欄。 – 2014-10-19 16:51:29

0

你可以使用drag'n'drop。
假設您有一個Form,其中DataGridView的名稱爲dataGridView1

首先不要忘了讓拖放爲DataGridView

dataGridView1.AllowDrop = true; 

事件處理它取代的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; 
     } 
    } 
} 

編輯
新方法:

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; 
    } 
} 
+0

謝謝...它適用於拖ñ滴,但當我不斷洗牌,然後int colIndexOfItemUnderMouseToDrop = dataGridView1.HitTest(clientPoint.X,clientPoint.Y) .ColumnIndex給出錯誤的索引,我正在丟棄。 – 2014-10-19 11:35:43

+0

看看接下來的3行。 'colIndexOfItemUnderMouseToDrop'正在糾正:'colIndexOfItemUnderMouseToDrop = dataGridView1.Columns [colIndexOfItemUnderMouseToDrop] .DisplayIndex;' – Dmitry 2014-10-19 11:57:03

+0

@AnkitSingh是否足夠清楚?如果是這樣,答案有幫助嗎? – Dmitry 2014-10-19 14:19:37

相關問題