VB 2013将列表框选定项目传递给后台工作者

时间:2014-07-10 11:45:29

标签: vb.net visual-studio-2013 arguments backgroundworker

我需要将表单控件中的数据传递给后台工作程序。我已经使用文本框和列表框中的一个选定项目来完成此操作。请参阅以下内容:

Public Class BackgroundWorkerArguments

    Public StartName1 As String

End Class

Private Sub RunButton1_Click(sender As Object, e As EventArgs) Handles RunButton1.Click

    Dim Arguments As BackgroundWorkerArguments = New BackgroundWorkerArguments()

        Arguments.StartName1 = StartNameListBox.SelectedItem

End Sub

Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork

Dim Arguments As BackgroundWorkerArguments = CType(e.Argument, BackgroundWorkerArguments)

Dim StartName As String = Arguments.StartName1 

End Sub

我希望在循环中实现此功能,以添加所有列表框选定的项目。我在按钮点击中尝试了这个:

For Each s As String In StartNameListBox1.SelectedItems()

        Arguments.StartName1 = s

    Next

要在我尝试的后台工作人员中恢复:

Dim Arguments As BackgroundWorkerArguments = CType(e.Argument, BackgroundWorkerArguments)

    For Each s As String In Arguments.StartName1

        Dim StartName As String = s

    Next

但是它只返回一个字符。无论如何,我有一个循环,对于选中的列表框中的每个文件夹名称,它会拉上这些文件夹。当我运行程序时,出现的zip是空的,最多只有一个字符。如果我只使用一个选定项目的第一个方法一切正常。所以我太遥远了!如果有人能指出我的方向,请告诉我。谢谢!

更新:

' Fills path of browsed folder into first text box.

    If (FolderBrowserDialog1.ShowDialog() = Windows.Forms.DialogResult.OK) Then
        StartPathTextBox1.Text = FolderBrowserDialog1.SelectedPath
        StartNameListBox1.Items.Clear()

        ' Fills foldernames within browsed folder into listbox.

        For Each s As String In System.IO.Directory.GetDirectories(StartPathTextBox1.Text)
            StartNameListBox1.Items.Add(IO.Path.GetFileName(s))
        Next

1 个答案:

答案 0 :(得分:0)

来自MSDN:You must be careful not to manipulate any user-interface objects in your DoWork event handler. Instead, communicate to the user interface through the ProgressChanged and RunWorkerCompleted events.有很多方法可以解决这个问题,但由于需要的主UI访问权限是更新ProgressBar,因此ProgressChanged事件就足够了。

有一个更大的问题。 BGW将使UI保持响应,这意味着当您在BGW 中处理项目时,用户可以从SelectedItems 添加,更改或删除项目。集合的内容在处理过程中不允许更改,或者您的代码可能会耗尽项目或遗漏项目。

也许更重要的是,依赖像TextBoxes和ListBoxes这样的UI控件会无情地将代码逻辑绑定到该表单上,这使得在其他程序中移动和重用代码变得很困难。您可以使用List变量来存储要执行的操作列表,而不是ListBox。这将使用List (of String)

Public Class Form1

    ' module/form level variables for our use
    Private allFilesAs List(Of String)
    Private zFolder As String

    ' in form load, create instance
    allFiles = New List(of String)

然后加载文件的过程:

Private Sub Button1_Click(...etc

    ' clear datasource for when user selects a new folder
    filesLB.DataSource = Nothing

    Using fb As New FolderBrowserDialog
        ' use old name as starting point if set
        If String.IsNullOrEmpty(zFolder) Then
            zFolder = Environment.GetFolderPath(_
                   Environment.SpecialFolder.MyDocuments)
        End If
        fb.SelectedPath = zFolder 

        If fb.ShowDialog() = Windows.Forms.DialogResult.Cancel Then Exit Sub

        zFolder = fb.SelectedPath

        ' display selection, but do not allow text edit           
        labelFolder.Text = zFolder 
    End Using

    zFiles.Clear()         ' clear the list from last time

    ' loop thru files
    For Each s As String In System.IO.Directory.GetFiles(zFolder)

        ' add to list
        allFiles.Add(IO.Path.GetFileName(s))
    Next

    ' set datasource of listbox to this list
    ' contents of myFiles will automagically appear
    filesLB.DataSource = allFiles

End Sub

数据实际上在我们的allFiles列表变量中。使用它作为ListBox.Datasource允许它在那里显示列表而不复制数据。如果您的代码要对列表进行许多更改,则可以使用BindingList(Of T),并在更新时在UI中显示这些更改。

  

请注意,如果您正在处理来自不同文件夹的文件,则需要类似FileClass的内容来存储带有每个文件的文件夹名称。自定义FileClass和List(Of FileClass)将允许这种灵活性。

目前,您正在关闭路径然后将其从用户可能已更改为无效位置的文本框中重新粘贴。这会将文件夹保存到zFolder变量并重复使用。

有几种方法可以处理列表。 SelectedItems是一个有效的集合,在许多情况下可以用作待办事项列表。如上所述,如果您正在使用BackgroundWorker,用户可以在处理它时更改该集合,因此我们将项目复制到新列表以防止这种情况发生。我没有使用第二个UI ListBox,因为用户已经可以看到所选内容,因此它是多余的;此列表供我们使用:

zFiles = New List(Of String)

' harvest selected files
For Each o As Object In filesLB.SelectedItems
    ' Selected items contains Object, cast back
    ' to string for the List
    zFiles.Add(Path.Combine(zFolder, CType(o, String))
Next

' ToDo: Zip the files in that zFiles list.

要压缩的文件列表不在UI中,而是在我们的变量控制之下。


最佳方式将创建一个Zipper类,其中所有与zip相关的过程都是encapsulated。它们很可能与表单代码混合在一起,并且可能都在事件过程中。 Zipper Class将从UI中分离核心逻辑,并通过将Zip类添加到该项目,让您更快地创建其他Zip相关程序。我们喜欢reusable代码,这可能比BGW更值得学习。在这种情况下,上面的zFiles可以是集合属性:

Private Z AS New Zipper

'...
For Each o As Object In filesLB.SelectedItems

    Z.Files.Add(Path.Combine(zFolder, CType(o, String))

Next
Z.Zip          ' method to process indicated files