Это похоже на ответ Стива, но использует 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
If nvp1.Value <> nvp2.Value Then...
. Причина в том, что что-то вроде {Plutonium, 94} значение обычно является важной частью, а имя является удобочитаемой/понятной для человека версией. Хотя могло быть и иначе (значение == некоторый индекс имени}. Эта версия довольно базовая - вы можете усилить ее с помощью пользовательского компаратора (приложение к приложению), чтобы использовать = / ‹› для сравнения любых частей) . 17.01.2016Equals
не =/‹› но срок отсрочки редактирования комментария истек. см. такжеImplements IEquatable(Of NVP)
17.01.2016Imports
вместо этого. Также есть ли причина, по которой первое поле со списком пропускается? 17.01.2016IEquatable
? Нет, это не требуется для перегрузкиEquals
, но есть случаи, когда это желательно: интерфейс - это контракт, который ваш тип может делать то или иное, другой код может спросить/увидеть, делает ли он это. Извините, нет, я не могу общаться 17.01.2016