gpt4 book ai didi

c# - 如何在 DataGridView 中模仿 Windows 资源管理器的多选/拖放行为?

转载 作者:行者123 更新时间:2023-11-30 15:49:14 26 4
gpt4 key购买 nike

我正在尝试模仿 Windows 资源管理器处理多项选择的方式。在默认的 DataGridView 中,您可以使用 Ctrl 键单击来选择多个项目。但是,如果您释放 Ctrl 键,然后尝试拖/放所选项目,它会清除所选项目并仅选择“命中”行。我在网上某处找到了以下解决方案。

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

但是,这会导致其他副作用。按住 CTRL 键并在所选项目上按住鼠标,该项目将保持选中状态。这是有道理的,因为如果选择了单击的行,则会绕过 mousedown 事件。从 Windows 资源管理器的行为来看,似乎直到 MouseUp 事件才处理取消选择按住 CTRL 键的项目。有没有人试过这样做?

最佳答案

我已经创建了一个自定义组件来解决这个问题,以及我在 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);
}
}
}

关于c# - 如何在 DataGridView 中模仿 Windows 资源管理器的多选/拖放行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1942636/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com