Множественный выбор Listview

Есть ли способ заставить элемент управления listview обрабатывать все щелчки так, как если бы они были выполнены с помощью клавиши Control?

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

Заранее спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
0
14 552
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Поведение Ctrl + Click реализуется браузером и имеет мало общего с самим .NET Control. Результат, которого вы пытаетесь достичь, может быть получен с помощью большого количества дополнительного JavaScript - вероятно, проще всего было бы создать элемент управления JavaScript по умолчанию, который работает таким образом, а не пытаться взломать представление списка. Было бы это желательно? В этом случае я мог бы изучить это и вернуться к вам с решением.

Ничего общего с браузером, он использует C# и WinForms!

Ray Hayes 17.09.2008 18:57

В любом случае, спасибо, Javascript нельзя использовать в среде winforms.

Evan 17.09.2008 18:58
Ответ принят как подходящий

Это не стандартное поведение элемента управления ListView, даже если для MultiSelect задано значение true.

Если вы хотите создать свой собственный настраиваемый элемент управления, вам нужно будет сделать следующее:

  1. Получение элемента управления из ListView
  2. добавить обработчик к событию «Выбрано».
  3. В «OnSelected» ведите собственный список выбранных элементов.
  4. Если только что выбранного элемента нет в вашем списке, добавьте его. Если это так, удалите его.
  5. В коде выберите все элементы в вашем списке.

Должен быть достаточно простым для реализации и ощущаться как множественный выбор без использования клавиши управления!

Я сам работал в этом направлении, но хотел проверить, есть ли что-нибудь попроще, прежде чем приступить к исправлению. Спасибо за ответ.

Evan 17.09.2008 19:01

Убедитесь, что в списке выбранных элементов хранится «содержимое», а не индекс. Использовать индекс проще, но это означает, что вам нужно синхронизировать ListBox.ItemsCollection и ваш список. Надеюсь, ваш объект или строка достаточно уникальны, чтобы сохранить эту связь!

Ray Hayes 17.09.2008 19:19

Просмотрите список 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();
    }
}

На всякий случай, если кто-то еще искал и нашел эту статью, принятое решение больше не действует. (на самом деле я не уверен, что это когда-либо было). Чтобы делать то, что вы хотите (выбрать несколько без клавиши-модификатора), просто установите тип выбора представления списка как множественный, а не расширенный. Множественный выбор одного элемента за другим при щелчке, а расширенный требует, чтобы сначала была нажата клавиша-модификатор.

Это не дает ответа на вопрос. Как только у вас будет достаточно репутация, вы сможете комментировать любой пост; вместо этого дать ответы, не требующие пояснений от спрашивающего. - Из обзора

Jason Yost 08.10.2016 21:15

Не знаю, как это не дает ответа на вопрос. Возник вопрос: «Есть ли способ заставить элемент управления списком обрабатывать все щелчки так, как если бы они были сделаны с помощью клавиши Control?» и ответ, который я дал, был «установить свойство множественного выбора как множественное, а не расширенное». Это действительный, правильный и проверенный ответ на исходный вопрос. Ну что ж, это последний раз, когда я пытаюсь помочь другим, которые сталкиваются со старым вопросом со старым решением.

kamikazi 10.10.2016 11:41

Другие вопросы по теме