CheckBoxをクリックしたときに、ListBoxのすべての項目を選択する必要があります。 1行のコードを使用して、ListBoxのすべての項目を選択することは可能ですか?それとも、すべてのアイテムをループして、それぞれのアイテムを選択してtrueに設定する必要がありますか?
ありがとう:)
ここでループする必要があると思います。一度にすべてのアイテムを選択することは、非常に具体的な(そしておそらくまれな)ユースケースであり、そのままの機能を提供することは単に意味がありません。さらに、ループはとにかく2行のコードになります。
実際はListBox.Items
は単純なオブジェクトコレクションであり、型なしの単純なオブジェクトを返します。複数のオブジェクトを選択することはできません(デフォルト)。
すべてのアイテムを複数選択する場合、これは機能します。
for (int i = 0; i < myListBox.Items.Count;i++)
{
myListBox.SetSelected(i, true);
}
私の知る限り、.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));
私は論理的に同じことをする多くの(類似した)答えをすべて見てきましたが、なぜそれらすべてが私にとってうまくいかないのか困惑しました。重要なのは、リストボックスの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
OR
lb.SelectionMode = SelectionMode.MultiSimple;
for (int i = 0; i < lb.Items.Count; i++)
lb.SelectedIndices.Add(i);
lb.SelectionMode = //back to what you want
私はミカのソリューションを使用しますが、何千ものアイテムがある場合、これは非常に遅くなる可能性があります。大幅な速度向上のために、一時的に表示をオフにすることができます。疑わしいかもしれませんが、操作中にリストボックスは実際には消えませんが、私の場合、選択は少なくとも10倍速く行われます。
myListBox.Visible = false;
for (int i = 0; i < myListBox.Items.Count;i++)
{
myListBox.SetSelected(i, true);
}
myListBox.Visible = true;
このコンストラクター内で、目的のテキストボックスの複数選択モード(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]ボタン+左クリックを使用して、アイテムを個別に選択することもできます。
私はこの質問に.NET 2.0のタグが付いていることを知っていますが、3.5以降でLINQを使用できる場合は、次のことを実行できます。
ASP.NET Webフォーム
var selected = listBox.Items.Cast<System.Web.UI.WebControls.ListItem>().All(i => i.Selected = true);
WinForms
var selected = listBox.SelectedItems.Cast<int>().ToArray();
すべて選択はすぐに使用できます。
$("#ListBoxID option").prop("selected", true);
これは絶対にナイスではありませんが、多くの(100以上の)アイテムがある場合、ループよりはるかに高速です。リストボックスを選択し、[home]と[shift] + [end]のキー入力をシミュレートします。
lb.BeginUpdate();
lb.Select();
SendKeys.Send("{Home}");
SendKeys.Send("+{End}");
lb.EndUpdate();
編集:SelectionMode.MultiExtendedでのみ機能します
DoubleEDit:これは、後でlb.selecteditemsを使用して実行されるコードには遅すぎる可能性があることにも注意してください。ただし、ユーザーがクリックする[すべて選択]ボタンには役立ちます。
私の場合、10,000個以上のアイテムがあったので、基本的なループ方法は完了するまでに1分近くかかっていました。 @DiogoNeves回答を使用してそれを拡張すると、すべてを選択(Ctrl + A)およびコピー(Ctrl + C)できるようになりました。私はこれを2つの方法で処理しました。 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();
}
}
すでに持っていたものに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;
}