从列表框中获取选定的项目

Getting Selected Items from a Listbox

周三好。

我 运行 进入一堵砖墙(树荫编码员很容易做到)我有一个列表框,其中填充了一个数据表。我想从所选项目中获取所有 LicenseID。换句话说,如果用户从列表框中的 8 个中选择 3 个,我需要为这 3 个中的每一个获取 LicenseID。

下面是我填充列表框的方式

 Using cmd As New OleDbCommand(cmdText, conn)
            conn.Open()
            Dim reader As OleDbDataReader = cmd.ExecuteReader()
            dt.Load(reader)
            ListBox1License.DataSource = dt
            ListBox1License.DisplayMember = "InstitutionTypeAbrev"
            ListBox1License.ValueMember = "LicenseID"

        End Using

我需要从列表框中获取所选项目以备后用。

我正在考虑将所选项目添加到数组中。

我在 Whosebug 周围搜索了一些示例,但 none 似乎对我有用。

感谢任何帮助

标准 ListBox 无法帮助您解决这个问题,因为它无法从 SelectedItems 集合中获取 DataRowView 对象。作为替代方案,您可以使用以下自定义控件代替标准 ListBox 来帮助您:

Public Class ListBoxEx
    Inherits ListBox
 
    Public Function GetItemValue(item As Object) As Object
        Dim index = Me.Items.IndexOf(item)
 
        If (index <> -1 AndAlso Me.DataManager IsNot Nothing) Then
            Return Me.FilterItemOnProperty(Me.DataManager.List(index), Me.ValueMember)
        End If
 
        Return Nothing
    End Function
 
End Class

然后您可以调用 GetItemValue 并传递任何项目并获得相同的值,如果那是 SelectedItem 并且您得到了 SelectedValue。获取数组中的所有值:

Dim licenseIDs = myListBoxEx.SelectedItems.
                             Cast(Of Object)().
                             Select(Function(o) CInt(myListBoxEx.GetItemValue(o)).
                             ToArray()

有关详细信息,请参阅 here

如果你不知道,如果你添加一个 class 到你的项目并且它是一个控件或组件,一旦你构建,它会自动出现在 的顶部工具箱 window.

如果您已经有了标准 ListBox 并且不想删除它并添加新控件,则可以手动编辑设计器代码文件以更改现有控件。为此,打开 Solution Explorer 和 select 项目中的一个节点,单击 Show All Files 按钮,展开节点对于您的表单,double-click 设计器代码文件,然后在相关位置将 ListBox 替换为 ListBoxEx(或任何您称之为的名称)。我建议先创建一个备份副本或与源代码管理同步,以防你搞砸了。

我会告诉你如何自己推导出答案:

我设置了一个表格:

真的很简单;列表框就像您的列表框。按钮就在那里,让我可以轻松地停止代码并检查正在发生的事情。

我写了一些代码来将一些东西填充到我的列表框中。这是一个屏幕截图,因为您完全拥有这段代码并不重要,所以您不需要编写这段代码(因此我很难复制粘贴):

我已经双击了我的按钮以制作点击处理程序。我没有编写任何代码,但我在方法声明上放置了一个断点——看到它是红色的了吗?单击点所在的边距,在代码中放置断点。当你点击它们时,代码停止并等待你检查:

我已经 运行 我的应用并点击了我的按钮。代码已停止,VS 已切换为向我显示代码,而不是应用程序:

我现在可以指向范围内的一些变量(如 ListBox1)并查看工具提示,或者我可以打开 Locals/Autos windows 并查看范围内的变量并深入研究他们:

在Autos/Localswindow中展开你的ListBox。它有很多属性。滚动到 SelectedItems:

SelectedItems 是一个东西的集合.. 我们可以看出一部分是因为微软擅长用复数名称命名东西的集合,并且因为检查员说“enumerate the enumerable”.. 意味着它是一堆我们可以通过 ForEach 查看的事物的数量

展开它我们看到我的 selecteditems 只选择了一个东西(当我点击按钮时我确实在我的列表中只有一个选择的项目)

我们可以看到SelectedItems集合中的一个条目是一个DataRowView类型的对象。我们可以看到 DataRowView 有一个 Row 属性 是一个 DataRow.. 这个 Row 是列表绑定到的 DataTable 中的 DataRow(您将 DataSource 设置为 DataTable;这是来自 table).

每次你深入树的另一个层次,就像在你的代码中使用一个点或一个索引器。在这个级别,我们已经走了 listbox1.SelectedItems(0).Row..

所以从这里我们可以看出我们需要这样的代码:

' we will "enumerate the enumerable"
For Each drv as DataRowView in listbox1.SelectedItems

  Dim originalRow = drv.Row  'we could do this to get the row...

  Dim selectedAnimaId = row("AnimalID") ' ..and then index the row to get the animal ID ..

  Dim selectedAnimalId = drv("AnimalID") ' ... or it's actually possible to index a DataRowView directly, so you can skip the row part

Next drv

当你在断点处停止时编写代码会很方便这样你就可以在编写代码时查看事物的值,并检查你是否朝着正确的方向前进。您可能需要使用 F10(或与“跳过”/“进入”关联的任何键)移动黄色条并逐行执行代码行:

如果您编写了完整、合法的代码,您只能继续执行代码,但它不一定在逻辑上是正确的。您可以通过拖动边缘的黄色箭头(或右键单击并选择“设置下一条语句”)来备份并再次执行。在这里,我放入了一些虚拟语句以继续前进,因此我可以检查我的 animalID 是否像我期望的那样在 X 中正确设置。我指向 X 以查看值: