2009-12-21 76 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); 
     } 
    } 
} 
相关问题