Хобрук: Ваш путь к мастерству в программировании

Удаление или отключение элемента ComboBox, который выбран в другом списке

У меня есть три поля со списком на WinForm следующим образом:

                  ___________________________
ComboBox List 1: |_______________________|___|
                  ___________________________
ComboBox List 2: |_______________________|___|
                  ___________________________
ComboBox List 3: |_______________________|___|

Каждое из этих полей со списком будет иметь во время разработки список «A», «B», «C».

По умолчанию список 1 является единственным активным в форме, а список 2 и список 3 станут активными, когда их предшественнику будет предоставлен выбор.

Что я хотел бы сделать, так это то, что если пользователь выбирает вариант C, я бы хотел, чтобы вариант C больше не был доступен для списка 2 и 3.

Я знаю, что это будет связано с событием .SelectedIndexChanged выпадающего списка, но не знаю, с чего начать кодирование.

Я нашел следующий ответ на StackOverflow, как моя ситуация не применима, поскольку я предоставляю элементы во время разработки, а не через импорт файла: vb.net изменить параметры поля со списком в зависимости от выбранного элемента в двух предыдущих полях со списком

16.01.2016

Ответы:


1

Это похоже на ответ Стива, но использует DataSource. Кроме того, нет реальной необходимости Enable/Disable каждого CBO. По мере внесения изменений предыдущие выборки отфильтровываются из источника. Любые повторяющиеся «предыдущие» изменения отменяются.

CBO1 всегда имеет полный список, в то время как другие пропускают предыдущие выборы. Вы не можете получить дубликаты выбора, потому что повторный выбор № 2 таким же, как № 3, изменяет содержимое № 3, заменяя выбор тем, что находится первым в списке.

' the master list
Private OptList As New List(Of String)
Private ignore As Boolean

' initialize somewhere:
OptList.AddRange(New String() {"Red", "Green", "Blue", "Violet", "Orange"})
' set up cbos
' ignore changes while setting up:
ignore = True
cb1.DataSource = OptList.ToArray
cb1.SelectedIndex = -1
cb2.DataSource = OptList.ToArray
cb2.SelectedIndex = -1
cb3.DataSource = OptList.ToArray
cb3.SelectedIndex = -1
ignore = False

Когда они все включены, они могут выбирать их в любом порядке.

Private Sub cbo_SelectedIndexChanged(sender As Object, e As EventArgs) _
             Handles cb1.SelectedIndexChanged, cb2.SelectedIndexChanged
    If ignore Then Exit Sub

    Dim cbo = TryCast(sender, ComboBox)
    If cbo IsNot Nothing AndAlso cbo Is cb1 Then
        cb2.DataSource = GetFilteredList(New String() {cb1.Items(cb1.SelectedIndex)})
    Else
        cb3.DataSource = GetFilteredList(New String() {cb1.SelectedItem.ToString,
                                                   cb2.SelectedItem.ToString})
    End If
End Sub

Private Function GetFilteredList(items As String()) As String()
    Return OptList.Except(items).ToArray()
End Function

Поскольку cbo3 ограничен теми предметами, которые не выбраны в #1 или #2 (раб), вам не нужно ничего делать, когда этот выбор изменится.


Could this be expanded to say 9 cbo by continuing multiple if/else statements и How would I keep the first option. Say if I wanted to include a "None" option always available.

Что то много, я бы сделал это более абстрактно. Код может быть сложнее читать/следовать, но его меньше (я использовал 4 cbos). Это может потребовать некоторой настройки, так как это не в моей голове для последующей исправленной формы:

' additional array to hold the CBOs involved
Private tgtCBOs As ComboBox()
...
' initialization:
OptList.AddRange(New String() {"(None)", "Red", "Green", "Blue", "Violet", 
                       "Orange", "Mauve", "White"})
tgtCBOs = New ComboBox() {cb1, cb2, cb3, cb4}

' set initial index to 0 with a default item

Private Sub cb2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles _ 
        cb2.SelectedIndexChanged, cb1.SelectedIndexChanged, cb3.SelectedIndexChanged

    If ignore Then Exit Sub

    Dim cbo = TryCast(sender, ComboBox)
    ' identify which one this is
    Dim ndx = Array.IndexOf(tgtCBOs, cbo)
    ' get all the selections from 0 to here
    Dim exclude = GetExclusionList(ndx)
    ' remove excludes from the NEXT cbo
    Dim newList As New List(Of String)
    If ndx + 1 < tgtCBOs.Length Then
        newList = OptList.Except(exclude).ToList()
        If newList(0) <> OptList(0) Then newList.Insert(0, "(None)")
        tgtCBOs(ndx + 1).DataSource = newList.ToArray()
    End If
End Sub

Private Function GetExclusionList(ndx As Int32) As List(Of String)
    Dim exclude As New List(Of String)
    For n As Int32 = 0 To ndx
        If tgtCBOs(n).SelectedIndex <> -1 Then
            exclude.Add(tgtCBOs(n).Items(tgtCBOs(n).SelectedIndex).ToString())
        End If
    Next
    Return exclude
End Function

Обратите внимание, что последний cbo не подключен к этому обработчику, потому что у него нет «ведомого». Подключите его к собственному обработчику, если вам нужно отреагировать на событие.

Кроме того, действие сброса DataSource для «следующего» (или очистки элементов в этом отношении) вызовет срабатывание этого события для следующего/дочернего/ведомого CBO. Таким образом, изменение CBO2 вызовет событие для 3, 4, 5..n. Он также сбрасывает предыдущий выбор в дочерних/ведомых/следующих.

16.01.2016
  • Может ли это быть расширено до 9 cbo, продолжая несколько операторов if/else? 17.01.2016
  • Хорошо... Второй вариант работает! Есть только одна маленькая проблема. Как бы я сохранил первый вариант. Скажем, если бы я хотел, чтобы опция «Нет» всегда была доступна. Я не вижу, как сохранить выбор варианта. 17.01.2016
  • @Plutonix Сэр, я должен вам выпить ... Я занимался этим всю ночь и даже смог (вроде) поработать с ответом NVP, который вы дали мне несколько месяцев назад. (Забавная вещь о повторном использовании кода...) stackoverflow.com/questions/31777645/. Всего один вопрос. Почему, когда я использую это, первый список опций не хочет обновляться? 17.01.2016
  • Вот он... Я искал этот ответ на днях. Я не мог вспомнить достаточно о вопросе или ответе, чтобы найти его 17.01.2016
  • @Plutonix: Только один вопрос, как вы определяете ‹› Для пользовательского типа данных, такого как NVP? 17.01.2016
  • Поскольку они являются объектами, вы можете проверить, только если они ссылаются на один и тот же объект. Они универсальны, поэтому их можно использовать по-разному, но обычно я бы сравнил значение. If nvp1.Value <> nvp2.Value Then.... Причина в том, что что-то вроде {Plutonium, 94} значение обычно является важной частью, а имя является удобочитаемой/понятной для человека версией. Хотя могло быть и иначе (значение == некоторый индекс имени}. Эта версия довольно базовая - вы можете усилить ее с помощью пользовательского компаратора (приложение к приложению), чтобы использовать = / ‹› для сравнения любых частей) . 17.01.2016
  • @Plutonix: Извините за это, немного поиска в Google на самом деле привели меня к тому же точному ответу. (geekswithblogs.net/viktorbergman/archive /2007/04/16/) 17.01.2016
  • Да, и я имел в виду Equals не =/‹› но срок отсрочки редактирования комментария истек. см. также Implements IEquatable(Of NVP) 17.01.2016
  • @Plutonix: Подождите, извините, другая проблема. Это Imports вместо этого. Также есть ли причина, по которой первое поле со списком пропускается? 17.01.2016
  • что не требуется, IEquatable? Нет, это не требуется для перегрузки Equals, но есть случаи, когда это желательно: интерфейс - это контракт, который ваш тип может делать то или иное, другой код может спросить/увидеть, делает ли он это. Извините, нет, я не могу общаться 17.01.2016
  • @Plutonix: Нет, нет. Мое редактирование, должно быть, пришло слишком поздно. И мой палец скользнул по кнопке чата. Я имел в виду отражение импорта и другие подобные поверх моего кода. Дополнительный вопрос: есть ли причина, по которой код пропускает или не срабатывает в отношении первого поля со списком? 17.01.2016
  • Как это пропускается? Его содержимое никогда не изменится, но все, что в нем выбрано, должно быть удалено из списка для всех остальных, ЕСЛИ это НЕ None. В этом случае вы можете захотеть отключить элементы, если они не могут выбрать 2...N, если только в #1 нет допустимого выбора. CBOs, конечно, не знают ни одного из Blue 17.01.2016

  • 2

    Итак, предположим, что ваши поля со списком называются b1, b2 и b3. Все эти комбинации связаны с одним и тем же обработчиком событий SelectedIndexChanged, и (как вы говорите) вы установили начальные элементы в b1, b2 и b3 в фиксированный список строк.

    Теперь вы также должны установить для свойства Enabled b2 и b3 значение false и позволить выбору b1 управлять вашей логикой в ​​событии SelectedIndexChanged.

    Sub onIndexChanged(sender As Object, e As EventArgs)
        Dim b As ComboBox = CType(sender, System.Windows.Forms.ComboBox)
        If b.Equals(b1) Then
            If b1.SelectedIndex = -1 Then
    
                b2.Enabled = False
                b3.Enabled = False
            Else
                b2.Enabled = True
                b3.Enabled = False
                b2.Items.Clear()
                b3.Items.Clear()
                b2.Items.AddRange(b1.Items.Cast(Of String)() _
                 .Where(Function(x) x <> b1.SelectedItem.ToString()).ToArray())
            End If
        Else if b.Equals(b2) Then
            If b2.SelectedIndex <> -1 Then
    
                b3.Items.Clear()
                b3.Items.AddRange(b2.Items.Cast(Of String)(). _
                    Where(Function(x) x <> b2.SelectedItem.ToString()).ToArray())
                b3.Enabled = True
                b3.SelectedIndex = 0
            End If 
        End If 
    End Sub
    
    16.01.2016
    Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..