【问题标题】:Select all items from Listbox, add them all only once to a Listview through BackgroundWorker从 Listbox 中选择所有项目,通过 BackgroundWorker 将它们全部添加到 Listview
【发布时间】:2020-08-25 20:24:00
【问题描述】:

我最近在从列表框中选择所有项(仅一次!)并将它们添加到列表视图时遇到了一些问题。由于列表视图将包含大 内容以及避免 GUI 在执行此任务时冻结,我正在使用后台工作人员来处理此任务。

好的,这里是 BackgroundWorker_ProgressChanged 代码:

  For Each item In ListBox3.SelectedItems

    listView1.Items.Add(ListBox3.SelectedItem, ImageList1.Images.Count - 1).SubItems.Add("Test")
      ListView1.Items("Test").SubItems.Add("")
       Next
      For Each item As ListViewItem In ListView1.SelectedItems

      Next
     End Sub

上面编写的代码在列表视图中显示项目,但仅如果用户从 Listbox3 中选择某个项目并显示无限次从列表框中选择的项目,我希望它只显示 ONCE 所有 从列表框中选择的项目,在列表视图中。我想自动选择 ALL 项目,无需用户干预,我尝试了几种失败的方法。 有人可以提供这个问题的解决方案吗?谢谢。

【问题讨论】:

  • 首先,使用BackgroundWorker 是毫无意义的。与 UI 相关的任何事情本质上都是前台工作,因此将数据从一个控件移动到另一个控件显然是前台工作。 ProgressChanged event handler is executed on the UI thread so using a BackgorundWorker` 完全没有意义。
  • 另外,当想法是将数据添加到ListView,而不是从中获取数据时,循环遍历ListView 中的任何集合有什么意义,更不用说SelectedItems?这是一个示例,说明当您编写代码而不知道该代码必须做什么时会发生什么。我说的不仅仅是最终结果,而是实现目标的步骤。您需要先弄清楚代码必须做什么,然后在代码中实现这些步骤。如果你这样做了,那么你就不可能循环通过SelectedItems 的ListView。
  • 好的,所以我这样做了:对于 ListBox3.Items 中的每个项目,但是它会重复显示每个项目。如何在列表视图中仅显示一次?谢谢。
  • +1 表示 jmcilhinney 所说的所有内容,但只是想补充一下,甚至更改的进度实际上是在您的 UI 线程中。如用于更新 UI 以报告进度的名称所示。如果你真的想为此使用后台工作人员,你可能需要通过 args 参数传入 Listbox3.Items,然后在工作人员完成处理程序中处理结果
  • 至于为什么您在列表视图中获得了 3 次项目,根据您给我们的 sn-p,我看不出有什么明显的原因。认为我们需要多看看你的代码

标签: vb.net listview listbox backgroundworker


【解决方案1】:

我刚刚测试过,似乎在辅助线程上从 ListBox 获取项目不是问题,所以我错了。但是肯定会添加/设置项目,因此您需要将项目添加到 UI 线程上的ListView。这是一些对我有用的示例代码:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    BackgroundWorker1.RunWorkerAsync()
End Sub

Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Dim outputItems As New List(Of ListViewItem)

    For Each inputItem As String In ListBox1.Items
        outputItems.Add(New ListViewItem(inputItem))
    Next

    e.Result = outputItems
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    Dim items = DirectCast(e.Result, List(Of ListViewItem))

    ListView1.Items.AddRange(items.ToArray())
End Sub

【讨论】:

    【解决方案2】:

    问题是所有的屏幕重绘。如果您限制屏幕重绘,我猜您可能不需要后台工作人员。

    我使用了ListViewItems 的列表,因为我不知道会有多少。必须将列表转换为数组才能使用.AddRange。

    事实上,只有 .BeginUpdate 和 .EndUpdate 可能会加快速度以达到可接受的程度。

    我不确定ImageList 的使用,所以你可能不得不玩弄它。

    Private Sub OpCode()
        Dim items = From itm In ListBox1.Items 'or ListBox1.SelectedItems
                    Select CStr(itm)
        Dim lvItems As New List(Of ListViewItem)
        Dim imageIndex As Integer = ImageList1.Images.Count - 1
        For Each item In items
            Dim lvItem As New ListViewItem(item, imageIndex)
            lvItems.Add(lvItem)
        Next
        'ListView1.BeginUpdate()
        ListView1.Items.AddRange(lvItems.ToArray)
        'ListView1.EndUpdate()
    End Sub
    

    【讨论】:

    • 调用BeginUpdate 和EndUpdate 用于多次调用Add。如果你打电话给AddRange,它们是多余的。
    • @jmcilhinney 谢谢。我有点以为是腰带和吊带。
    猜你喜欢
    • 2013-07-07
    • 1970-01-01
    • 1970-01-01
    • 2014-06-03
    • 2016-10-06
    • 2017-12-31
    • 2020-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多