【发布时间】:2014-10-16 08:11:45
【问题描述】:
我需要将鼠标多选支持添加到 winform 列表视图。 (用户将单击一个项目并将其拖到第五个,她将能够选择项目 1 到 5)我认为我应该继承列表视图以向其添加新功能,但我不知道应该添加哪些事件或方法.我该怎么做?提前谢谢。
【问题讨论】:
标签: c# winforms listview multi-select onmouseover
我需要将鼠标多选支持添加到 winform 列表视图。 (用户将单击一个项目并将其拖到第五个,她将能够选择项目 1 到 5)我认为我应该继承列表视图以向其添加新功能,但我不知道应该添加哪些事件或方法.我该怎么做?提前谢谢。
【问题讨论】:
标签: c# winforms listview multi-select onmouseover
自定义 ListView 并覆盖 MouseMove(奖励 - Ctr+A 支持):
[System.ComponentModel.DesignerCategory("Code")]
public class MyListView : ListView
{
protected override void OnMouseMove(MouseEventArgs e)
{
// easy mouse selection
if (MouseButtons == MouseButtons.Left)
{
var item = this.HitTest(e.Location).Item;
if (item != null)
item.Selected = true;
}
base.OnMouseMove(e);
}
protected override void OnKeyDown(KeyEventArgs e)
{
// ctrl-a - select all
if (e.KeyCode == Keys.A && e.Control)
SelectAll();
base.OnKeyDown(e);
}
}
这不是最好的实现,如果你移动得太快,那么有些项目会被跳过。
ListView 是一个有点特殊的控件,因为它有不同的视图来呈现数据。在icon 视图中,您可以通过用鼠标绘制一个矩形 来选择多个项目(按下按钮、绘制矩形、释放)。 details 视图中的效果相同。所有与矩形相交的项目都将被选中。重要提示:这种选择方式需要从未被项目占用区域开始绘制矩形。
问题:在详细信息中查看位于最后一列右侧和最后一项底部的未占用区域。通常列占据所有水平空间,项目占据所有垂直空间,因此不存在这样的区域。所以这种选择方式是行不通的!
在ListView 中选择多个项目的其他众所周知的可能性是选择第一个项目,按Shift,然后单击最后一个项目。范围内的所有项目(或 icon 视图中的矩形)都将被选中。或者按住 Ctr 并单击项目以逐一切换它们的选择。
【讨论】:
ListView 中解释了选择。我不知道避免跳过项目的简单解决方案。也许您可以处理SelectionChanged事件(我希望它不会跳过选择)并查看是否按下了鼠标按钮,然后将之前已经选择的内容添加到选择中(将其存储在列表中,释放鼠标按钮后清除)。
Sinatrs 方法是个好主意。
使用“详细信息”视图,您可以尝试这样的操作,以获得类似于 Windows 资源管理器的行为:
Int32 firstClickItemIndex = 0;
public Boolean numInRange(Int32 num, Int32 first, Int32 last)
{
return first <= num && num <= last;
}
private void listView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.A && e.Control)
{
foreach (ListViewItem lvItem in listView1.Items)
lvItem.Selected = true;
}
}
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
if (MouseButtons == MouseButtons.Left && listView1.HitTest(e.Location).Item != null)
firstClickItemIndex = listView1.HitTest(e.Location).Item.Index;
}
private void listView1_MouseMove(object sender, MouseEventArgs e)
{
if (MouseButtons == MouseButtons.Left)
{
ListViewItem lvItem = listView1.HitTest(e.Location).Item;
if (lvItem != null)
{
lvItem.Selected = true;
if (listView1.SelectedItems.Count > 1)
{
Int32 firstSelected = listView1.SelectedItems[0].Index;
Int32 lastSelected = listView1.SelectedItems[listView1.SelectedItems.Count - 1].Index;
foreach (ListViewItem tempLvItem in listView1.Items)
{
if (numInRange(tempLvItem.Index, firstSelected, lastSelected) && (numInRange(tempLvItem.Index, lvItem.Index, firstClickItemIndex) || numInRange(tempLvItem.Index, firstClickItemIndex, lvItem.Index)))
{
tempLvItem.Selected = true;
}
else
{
tempLvItem.Selected = false;
}
}
}
}
}
}
【讨论】: