如何在选中复选框时选择列表框中的所有项目?
Posted
技术标签:
【中文标题】如何在选中复选框时选择列表框中的所有项目?【英文标题】:How do I select all items in a listbox on checkbox checked? 【发布时间】:2010-10-30 08:57:17 【问题描述】:单击 CheckBox 时,我需要选择 ListBox 中的所有项目。是否可以使用一行代码选择 ListBox 中的所有项目?还是我必须遍历所有项目并将每个项目的 selected 设置为 true?
【问题讨论】:
【参考方案1】:事实上ListBox.Items
是一个普通的对象集合,返回普通的无类型对象,不能多选(默认)。
如果您想多选所有项目,那么这将起作用:
for (int i = 0; i < myListBox.Items.Count;i++)
myListBox.SetSelected(i, true);
【讨论】:
假设此逻辑与在 KeyDown 事件中处理的组合键(例如 Ctrl+A)相关联,您还需要确保包含 e.SuppressKeyPress = true;否则它会将您的选择恢复为列表中的第一个“A”。 对于大型列表,应该暂停更新。 ***.com/q/15398091/340790【参考方案2】:我已经看到了许多(类似的)答案,它们在逻辑上都做同样的事情,我很困惑为什么它们都不适合我。关键是将列表框的SelectionMode
设置为SelectionMode.MultiSimple
。它不适用于SelectionMode.MultiExtended
。考虑在列表框中选择多个项目,您将选择模式设置为多个模式,并且大多数人会选择传统的MultiExtended
样式,这个答案应该会有很大帮助。而且你不是foreach
,而是for
。
你实际上应该这样做:
lb.SelectionMode = SelectionMode.MultiSimple;
for (int i = 0; i < lb.Items.Count; i++)
lb.SetSelected(i, true);
lb.SelectionMode = //back to what you want
或
lb.SelectionMode = SelectionMode.MultiSimple;
for (int i = 0; i < lb.Items.Count; i++)
lb.SelectedIndices.Add(i);
lb.SelectionMode = //back to what you want
【讨论】:
如果你添加e.SuppressKeyPress = true;
它应该可以工作,不管SelectionMode。【参考方案3】:
据我所知,使用任何 .NET 方法选择大量项目都比直接调用 PInvoke 慢得多,将 LB_SETSEL 消息 (0x185) 传递给控件,并带有一个标志指示是否您想要选择 (1) 或取消选择 (0) 以及表示更改应应用于所有项目的魔法值 (-1)。
[DllImport("user32.dll", EntryPoint = "SendMessage")]
internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam);
// Select All
SendMessage(listBox.Handle, 0x185, (IntPtr)1, (IntPtr)(-1));
// Unselect All
SendMessage(listBox.Handle, 0x185, (IntPtr)0, (IntPtr)(-1));
【讨论】:
不错的尝试。它确实选择了所有项目,但项目枚举失败。问题是,在 SendMessage 选择所有项目后,我得到 SelectedItems.Count 显示所有列表框项目的计数(这是正确的)。但是当我试图枚举 SelectedItems 时 - 只执行一次迭代。当我执行SelectedItems[SelectedItems.Count - 1]
IndexOutOfRange 时抛出异常。似乎选择了项目,但列表框不会用它们刷新内部列表。要计算SelectedObjectCollection.Count
属性,getter 发送另一个窗口消息,返回所有项目的计数。
-1 并不是那么神奇,请参阅LB_SETSEL message (Windows)。顺便说一句:它适用于 VCL 类 TListBox。
嗨,@Wolf。 “魔术”一词在编程中具有特殊的含义。见en.wikipedia.org/wiki/Magic_number_(programming)
是的,我知道。但有时 magic 也指可以更好地被符号常量替换的整数文字,而某些文字是首选的,例如 0。-1 对于基于 0 的索引的“例外”情况很突出,其中0(又名 NULL)不适合。
@Wolf:我没有遇到任何问题(我在 Fiddler 中使用了这种技术)。话虽如此,在执行选择后只允许发送消息(例如,通过调用 Application.DoEvents
)可能可以解决此问题。【参考方案4】:
我认为你必须在这里循环。一次选择所有项目是一个非常具体(并且可能很少见)的用例,开箱即用地提供该功能毫无意义。此外,无论如何,循环只是两行代码。
【讨论】:
【参考方案5】:我使用 Mika 的解决方案,但是如果您有数千个项目,这可能会非常慢。要大幅提高速度,您可以暂时关闭可见性。列表框在操作过程中实际上不会像您可能怀疑的那样消失,但在我的情况下,选择的速度至少快了 10 倍。
myListBox.Visible = false;
for (int i = 0; i < myListBox.Items.Count;i++)
myListBox.SetSelected(i, true);
myListBox.Visible = true;
【讨论】:
我相信myListBox.Visible = false
更快,因为它避免了在更新时绘制。我会使用myListBox.BeginUpdate()
和myListBox.EndUpdate()
提供的方法 :)
+1 评论 DiogoNeves。更好,因为它也会使焦点停留在列表框上。对于 Robin 的解决方案,必须在再次将其设置为可见后调用 myListBox.Focus()。【参考方案6】:
在此构造函数中,您需要启用所需文本框的多选模式(MultiExtended
)。
public Form1()
InitializeComponent();
listBox1.SelectionMode = SelectionMode.MultiExtended;
listBox2.SelectionMode = SelectionMode.MultiExtended;
在此之后,使用循环选择所有内容:
private void selectAll_Click(object sender, EventArgs e)
for (int val = 0; val < listBox1.Items.Count; val++)
listBox1.SetSelected(val, true);
我测试过了。有用。您也可以使用 [CTRL/SHIFT] 按钮 + 左键单击单独选择项目。
【讨论】:
【参考方案7】:在我的情况下,我有 10k+ 个项目,基本循环方法需要将近一分钟才能完成。使用@DiogoNeves 回答并扩展它,我希望能够全选(Ctrl+A)和复制(Ctrl+C)。我处理了这两种方式。我使用 BeginUpdate() 和 EndUpdate() 来推迟绘图,但我还添加了一个直接复制所有 (Ctrl+Shift+C),它甚至不需要在复制之前选择项目。
private static void HandleListBoxKeyEvents(object sender, KeyEventArgs e)
var lb = sender as ListBox;
// if copy
if (e.Control && e.KeyCode == Keys.C)
// if shift is also down, copy everything!
var itemstocopy = e.Shift ? lb.Items.Cast<object>() : lb.SelectedItems.Cast<object>();
// build clipboard buffer
var copy_buffer = new StringBuilder();
foreach (object item in itemstocopy)
copy_buffer.AppendLine(item?.ToString());
if (copy_buffer.Length > 0)
Clipboard.SetText(copy_buffer.ToString());
// if select all
else if (e.Control && e.KeyCode == Keys.A)
lb.BeginUpdate();
for (var i = 0; i < lb.Items.Count; i++)
lb.SetSelected(i, true);
lb.EndUpdate();
【讨论】:
【参考方案8】:如果你有很多(100+)项,这绝对不是很好,但比循环快得多: 选择Listbox,模拟[home]和[shift]+[end]的按键输入
lb.BeginUpdate();
lb.Select();
SendKeys.Send("Home");
SendKeys.Send("+End");
lb.EndUpdate();
编辑:我猜只适用于 SelectionMode.MultiExtended
DoubleEDit:还请注意,这对于之后使用 lb.selecteditems 执行的代码可能太慢,但对于用户将单击的 [全选] 按钮可能很有用。
【讨论】:
对我不起作用(使用 .Net 4.7)。列表框只是闪烁,仅此而已。【参考方案9】:全选绝对是开箱即用的:
$("#ListBoxID option").prop("selected", true);
【讨论】:
这个问题是针对winforms而不是web 此代码也不是开箱即用的。列出的代码是 jQuery 而不是 C#/VB.NET 答案是问题的适当解决方案!【参考方案10】:我知道这个问题是用 .NET 2.0 标记的,但是如果您在 3.5+ 中可以使用 LINQ,则可以执行以下操作:
ASP.NET 网络表单
var selected = listBox.Items.Cast<System.Web.UI.WebControls.ListItem>().All(i => i.Selected = true);
WinForms
var selected = listBox.SelectedItems.Cast<int>().ToArray();
【讨论】:
不 - 我得到 找不到类型或名称 ListItem。 (您是否缺少 Using 指令或程序集引用)。 对解决方案投反对票似乎有点过分,而不是与人一起找出解决方案可能不适合您的原因。您是否有提到的缺少使用指令using System.Web.UI.WebControls;
?您是否引用程序集?已更新答案以引用程序集。
对不起 fujiface - 我又给你投票了。我最初以为你是在 2014 年写的,所以我没想到会有回应。我似乎无法访问 System.Web.UI.WebControls。我只能看到 System.Web。我试图添加对它的引用,但它也没有出现在那里。也许它在 4.7 中已被弃用?我查找了具有该名称的 NuGet 包,但也不存在。
查看 MSDN 上的文档,我看到了 System.Web.UI.Design.WebControls 命名空间,但我似乎无法在我的代码中访问它。
没问题@Ben_G。那是个很好的观点。根据您拥有的项目类型(我的项目是基于 Web 的,并且 OP 大约在 2009 年使用 WinForms),您可能无法访问服务器控件。我并没有真正指定 ListItem 类型,因为问题被标记为 WinForms 并且仔细查看我的答案,它可能需要进一步调整以在 WinForms 上下文中。【参考方案11】:
我将nawfal 的想法添加到我已有的想法中,这也是'BeginUpdate'。另外,正如用户所期望的那样,视图位置也得到了维护。对我来说,这似乎解决了所有问题:
public void SelectAll()
bool prevBusy = MouseHelper.IsBusy;
MouseHelper.IsBusy = true;
int topIndex = TopIndex;
// BUG: In 'SelectionMode.MultiExtended' the box gets crazy
SelectionMode previousMode = this.SelectionMode;
this.SelectionMode = SelectionMode.MultiSimple;
this.BeginUpdate();
for (int i = 0; i < Items.Count; i++)
SelectedIndices.Add(i);
this.EndUpdate();
this.SelectionMode = previousMode;
TopIndex = topIndex;
MouseHelper.IsBusy = prevBusy;
【讨论】:
【参考方案12】:private void Button_Click(object sender, RoutedEventArgs e)
listbox.SelectAll();
【讨论】:
这是哪个版本的 .Net? WinForms ListBox 中没有 SelectAll 方法。您可能正在考虑 WPF ListBox,但这个问题被标记为“winforms”和“.net-2.0”。以上是关于如何在选中复选框时选择列表框中的所有项目?的主要内容,如果未能解决你的问题,请参考以下文章
当一个或多个项目被取消选择时,knockoutjs 取消选择/选择所有复选框