2009-12-21 37 views
3

我試圖模仿Windows資源管理器處理多個選擇的方式。在默認的DataGridView中,您可以使用Ctrl鍵單擊選擇多個項目。但是,如果您釋放Ctrl鍵,然後嘗試拖放所選項目,則會清除所選項目並僅選擇「命中」行。我在網上找到了以下解決方案。如何模仿Windows資源管理器在DataGridView中的多選/拖放行爲?

protected override OnMouseDown(MouseEventArgs e) 
{ 
    int hitRowIndex = HitTest(e.X, e.Y).RowIndex; 
    if(!SelectedRows.Contains(Rows[hitRowIndex])) 
    { 
    base.OnMouseDown(); 
    } 
} 

但是,這會導致其他副作用。按下CTRL鍵並將鼠標移到所選項目上,該項目保持選定狀態。這是有道理的,因爲如果選中了點擊行,mousedown事件將被繞過。從查看Windows資源管理器的行爲看,使用CTRL鍵取消選擇項目不會處理,直到MouseUp事件發生。有沒有人試圖做到這一點?

回答

0

可能是這樣幫助你:

protected override void OnMouseDown(MouseEventArgs e) 
    { 
     int hitRowIndex = HitTest(e.X, e.Y).RowIndex; 
     if ((!SelectedRows.Contains(Rows[hitRowIndex])) || ((ModifierKeys & Keys.Control) != Keys.None)) 
     { 
      base.OnMouseDown(e); 
     } 
    } 
4

我創建了一個自定義組件來解決這個問題,以及其他一些惱人的問題,我曾與datagridview的多項選擇。這是代碼,希望它可以幫助任何人:

public partial class CustomDataGridView : DataGridView 
{ 
    public CustomDataGridView() 
    { 
     InitializeComponent(); 
    } 
    public CustomDataGridView(IContainer container) 
    { 
     container.Add(this); 

     InitializeComponent(); 
    } 

    private bool _delayedMouseDown = false; 
    private Rectangle _dragBoxFromMouseDown = Rectangle.Empty; 

    private Func<object> _getDragData = null; 
    public void EnableDragDrop(Func<object> getDragData) 
    { 
     _getDragData = getDragData; 
    } 

    protected override void OnCellMouseDown(DataGridViewCellMouseEventArgs e) 
    { 
     base.OnCellMouseDown(e); 

     if (e.RowIndex >= 0 && e.Button == MouseButtons.Right) 
     { 
      var currentRow = this.CurrentRow.Index; 
      var selectedRows = this.SelectedRows.OfType<DataGridViewRow>().ToList(); 
      var clickedRowSelected = this.Rows[e.RowIndex].Selected; 

      this.CurrentCell = this.Rows[e.RowIndex].Cells[e.ColumnIndex]; 

      // Select previously selected rows, if control is down or the clicked row was already selected 
      if ((Control.ModifierKeys & Keys.Control) != 0 || clickedRowSelected) 
       selectedRows.ForEach(row => row.Selected = true); 

      // Select a range of new rows, if shift key is down 
      if ((Control.ModifierKeys & Keys.Shift) != 0) 
       for (int i = currentRow; i != e.RowIndex; i += Math.Sign(e.RowIndex - currentRow)) 
        this.Rows[i].Selected = true; 
     } 
    } 
    protected override void OnMouseDown(MouseEventArgs e) 
    { 
     var rowIndex = base.HitTest(e.X, e.Y).RowIndex; 
     _delayedMouseDown = (rowIndex >= 0 && 
      (SelectedRows.Contains(Rows[rowIndex]) || (ModifierKeys & Keys.Control) > 0)); 

     if (!_delayedMouseDown) 
     { 
      base.OnMouseDown(e); 

      if (rowIndex >= 0) 
      { 
       // 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 datagridview. 
       _dragBoxFromMouseDown = Rectangle.Empty; 
     } 
    } 
    protected override void OnMouseUp(MouseEventArgs e) 
    { 
     // Perform the delayed mouse down before the mouse up 
     if (_delayedMouseDown) 
     { 
      _delayedMouseDown = false; 
      base.OnMouseDown(e); 
     } 

     base.OnMouseUp(e); 
    } 
    protected override void OnMouseMove(MouseEventArgs e) 
    { 
     base.OnMouseMove(e); 

     // If the mouse moves outside the rectangle, start the drag. 
     if (_getDragData != null && (e.Button & MouseButtons.Left) > 0 && 
      _dragBoxFromMouseDown != Rectangle.Empty && !_dragBoxFromMouseDown.Contains(e.X, e.Y)) 
     { 
      if (_delayedMouseDown) 
      { 
       _delayedMouseDown = false; 
       if ((ModifierKeys & Keys.Control) > 0) 
        base.OnMouseDown(e); 
      } 

      // Proceed with the drag and drop, passing in the drag data 
      var dragData = _getDragData(); 
      if (dragData != null) 
       this.DoDragDrop(dragData, DragDropEffects.Move); 
     } 
    } 
} 
相關問題