Есть ли способ заставить элемент управления listview обрабатывать все щелчки так, как если бы они были выполнены с помощью клавиши Control?
Мне нужно воспроизвести функциональность использования клавиши управления (выбор элемента устанавливает и отменяет его статус выбора), чтобы пользователь мог легко выбирать несколько элементов одновременно.
Заранее спасибо.





Поведение Ctrl + Click реализуется браузером и имеет мало общего с самим .NET Control. Результат, которого вы пытаетесь достичь, может быть получен с помощью большого количества дополнительного JavaScript - вероятно, проще всего было бы создать элемент управления JavaScript по умолчанию, который работает таким образом, а не пытаться взломать представление списка. Было бы это желательно? В этом случае я мог бы изучить это и вернуться к вам с решением.
В любом случае, спасибо, Javascript нельзя использовать в среде winforms.
Это не стандартное поведение элемента управления ListView, даже если для MultiSelect задано значение true.
Если вы хотите создать свой собственный настраиваемый элемент управления, вам нужно будет сделать следующее:
Должен быть достаточно простым для реализации и ощущаться как множественный выбор без использования клавиши управления!
Я сам работал в этом направлении, но хотел проверить, есть ли что-нибудь попроще, прежде чем приступить к исправлению. Спасибо за ответ.
Убедитесь, что в списке выбранных элементов хранится «содержимое», а не индекс. Использовать индекс проще, но это означает, что вам нужно синхронизировать ListBox.ItemsCollection и ваш список. Надеюсь, ваш объект или строка достаточно уникальны, чтобы сохранить эту связь!
Просмотрите список ListviewItemCollection, и вы можете установить для свойства Selected для отдельных элементов значение true. Я считаю, что это будет имитировать функцию "множественного выбора", которую вы пытаетесь воспроизвести. (Кроме того, как упомянул вышеупомянутый комментатор, убедитесь, что для свойства MultiSelect lisetview установлено значение true.)
Вы можете также рассмотреть возможность использования Флажки в представлении списка. Это очевидный способ передать концепцию множественного выбора среднему пользователю, который может не знать о Ctrl + Click.
Со страницы MSDN:
The CheckBoxes property offers a way to select multiple items in the ListView control without using the CTRL key. Depending on your application, using check boxes to select items rather than the standard multiple selection method may be easier for the user. Even if the MultiSelect property of the ListView control is set to false, you can still display checkboxes and provide multiple selection capabilities to the user. This feature can be useful if you do not want multiple items to be selected yet still want to allow the user to choose multiple items from the list to perform an operation within your application.
Вот полное решение, которое я использовал для решения этой проблемы с помощью WndProc. По сути, он выполняет проверку нажатия при щелчке мышью ... затем, если MutliSelect включен, он автоматически включает / выключает элемент [.Selected] и не беспокоится о поддержании каких-либо других списков или возня с функциональностью ListView.
Я не тестировал это во всех сценариях, ... у меня это сработало. YMMV.
public class MultiSelectNoCTRLKeyListView : ListView {
public MultiSelectNoCTRLKeyListView() {
}
public const int WM_LBUTTONDOWN = 0x0201;
protected override void WndProc(ref Message m) {
switch (m.Msg) {
case WM_LBUTTONDOWN:
if (!this.MultiSelect)
break;
int x = (m.LParam.ToInt32() & 0xffff);
int y = (m.LParam.ToInt32() >> 16) & 0xffff;
var hitTest = this.HitTest(x, y);
if (hitTest != null && hitTest.Item != null)
hitTest.Item.Selected = !hitTest.Item.Selected;
return;
}
base.WndProc(ref m);
}
}
Вот полное решение, которое является модификацией решения, предоставленного Мэтью М. выше.
Он предлагает улучшения, а также немного дополнительных функций.
Улучшение:
Добавлен функционал:
MultiSelectionLimit), которое позволяет вам ограничить количество элементов, которые можно выбрать одновременно.После первой публикации я обнаружил небольшую проблему с кодом. Очистка множественного выбора приведет к многократному вызову события ItemSelectionChanged.
Я не мог найти способа избежать этого с текущим наследованием, поэтому вместо этого я принял решение, в котором свойство bool SelectionsBeingCleared будет истинным до тех пор, пока все выбранные элементы не будут отменены.
Таким образом, простой вызов этого свойства позволит избежать обновления эффектов до тех пор, пока не будут очищены все множественные выборки.
public class ListViewMultiSelect : ListView
{
public const int WM_LBUTTONDOWN = 0x0201;
public const int WM_RBUTTONDOWN = 0x0204;
private bool _selectionsBeingCleared;
/// <summary>
/// Returns a boolean indicating if multiple items are being deselected.
/// </summary>
/// <remarks> This value can be used to avoid updating through events before all deselections have been carried out.</remarks>
public bool SelectionsBeingCleared
{
get
{
return this._selectionsBeingCleared;
}
private set
{
this._selectionsBeingCleared = value;
}
}
private int _multiSelectionLimit;
/// <summary>
/// The limit to how many items that can be selected simultaneously. Set value to zero for unlimited selections.
/// </summary>
public int MultiSelectionLimit
{
get
{
return this._multiSelectionLimit;
}
set
{
this._multiSelectionLimit = Math.Max(value, 0);
}
}
public ListViewMultiSelect()
{
this.ItemSelectionChanged += this.multiSelectionListView_ItemSelectionChanged;
}
public ListViewMultiSelect(int selectionsLimit)
: this()
{
this.MultiSelectionLimit = selectionsLimit;
}
private void multiSelectionListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (e.IsSelected)
{
if (this.MultiSelectionLimit > 0 && this.SelectedItems.Count > this.MultiSelectionLimit)
{
this._selectionsBeingCleared = true;
List<ListViewItem> itemsToDeselect = this.SelectedItems.Cast<ListViewItem>().Except(new ListViewItem[] { e.Item }).ToList();
foreach (ListViewItem item in itemsToDeselect.Skip(1)) {
item.Selected = false;
}
this._selectionsBeingCleared = false;
itemsToDeselect[0].Selected = false;
}
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_LBUTTONDOWN:
if (this.SelectedItems.Count == 0 || !this.MultiSelect) { break; }
if (this.MultiSelectionLimit > 0 && this.SelectedItems.Count > this.MultiSelectionLimit) { this.ClearSelections(); }
int x = (m.LParam.ToInt32() & 0xffff);
int y = (m.LParam.ToInt32() >> 16) & 0xffff;
ListViewHitTestInfo hitTest = this.HitTest(x, y);
if (hitTest != null && hitTest.Item != null) { hitTest.Item.Selected = !hitTest.Item.Selected; }
this.Focus();
return;
case WM_RBUTTONDOWN:
if (this.SelectedItems.Count > 0) { this.ClearSelections(); }
break;
}
base.WndProc(ref m);
}
private void ClearSelections()
{
this._selectionsBeingCleared = true;
SelectedListViewItemCollection itemsToDeselect = this.SelectedItems;
foreach (ListViewItem item in itemsToDeselect.Cast<ListViewItem>().Skip(1)) {
item.Selected = false;
}
this._selectionsBeingCleared = false;
this.SelectedItems.Clear();
}
}
На всякий случай, если кто-то еще искал и нашел эту статью, принятое решение больше не действует. (на самом деле я не уверен, что это когда-либо было). Чтобы делать то, что вы хотите (выбрать несколько без клавиши-модификатора), просто установите тип выбора представления списка как множественный, а не расширенный. Множественный выбор одного элемента за другим при щелчке, а расширенный требует, чтобы сначала была нажата клавиша-модификатор.
Это не дает ответа на вопрос. Как только у вас будет достаточно репутация, вы сможете комментировать любой пост; вместо этого дать ответы, не требующие пояснений от спрашивающего. - Из обзора
Не знаю, как это не дает ответа на вопрос. Возник вопрос: «Есть ли способ заставить элемент управления списком обрабатывать все щелчки так, как если бы они были сделаны с помощью клавиши Control?» и ответ, который я дал, был «установить свойство множественного выбора как множественное, а не расширенное». Это действительный, правильный и проверенный ответ на исходный вопрос. Ну что ж, это последний раз, когда я пытаюсь помочь другим, которые сталкиваются со старым вопросом со старым решением.
Ничего общего с браузером, он использует C# и WinForms!