VB.NET 如何反转 ProgressBar

VB.NET How To Reverse ProgressBar

所以我创建了一个 ProgressBar、BackgroundWorker、Timer 和一个统计文件夹内文件总数的标签。我想根据剩余文件的数量从 0% 到 100%。我的问题是它从 100% 开始,在删除文件时倒计时到 0%,因为“剩余文件”设置为 ProgressBar 的最大值。有没有一种简单的方法可以让它从 0% 开始并随着标签倒数到 0 而增加到 100%?下面是代码:

Private Sub BackgroundWorker2_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker2.DoWork
    Dim I = labelFileCount.Text
    '  labelFileCount.Text = I 'report to label
    BackgroundWorker2.ReportProgress(I) 'report
        System.Threading.Thread.Sleep(100)
End Sub

Private Sub BackgroundWorker2_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker2.ProgressChanged
    MetroProgressBar1.Value = e.ProgressPercentage
End Sub

Private Sub CountFiles(InFolder As String, ByRef Result As Integer)
    Result += IO.Directory.GetFiles(InFolder).Count
    For Each f As String In IO.Directory.GetDirectories(InFolder)
        CountFiles(f, Result)
    Next
End Sub

Private Sub CountFilesTimer_Tick(sender As Object, e As EventArgs) Handles CountFilesTimer.Tick
    Dim orderFolder As String
    orderFolder = My.Settings.Path & "\" & MetroTextBox1.Text
    Dim FileCount As Integer = 0
    CountFiles(orderFolder, FileCount)
    labelFileCount.Text = FileCount.ToString
End Sub

   Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click

    Dim orderFolder As String
    orderFolder = My.Settings.AgencyDataPath & "\" & MetroTextBox1.Text
    MsgBox(orderFolder)
    Dim FileCount As Integer = 0
    CountFiles(orderFolder, FileCount)
    MessageBox.Show(FileCount.ToString)
    labelFileCount = FileCount.ToString
    MetroProgressBar1.Maximum = Label1.Text
    CountFilesTimer.Start()
End Sub

更简单、更快速的方法。不需要计时器,也不需要按文件夹递归地重复计算文件。 Task.Run 将工作放在后台线程中,这需要 Me.Invoke 机制来正确更新 UI。

Imports System.IO

Public Class Form1
    Private FilesList As List(Of String)

    Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
        Button6.Enabled = False

        ' Capture list of all files in all subfolders
        FilesList = Directory.EnumerateFiles(Path.Combine(My.Settings.Path, MetroTextBox1.Text), "*", SearchOption.AllDirectories).ToList

        ' Initialize ProgressBar
        MetroProgressBar1.Value = 0
        MetroProgressBar1.Maximum = FilesList.Count

        ' Execute DeleteFiles in separate thread
        Task.Run(Sub() DeleteFiles())
    End Sub

    Private Sub DeleteFiles()
        For Each Filename As String In FilesList
            File.Delete(Filename)
            UpdateProgress()
        Next

        If Me.InvokeRequired Then
            Me.Invoke(Sub() Button6.Enabled = True)
        Else
            Button6.Enabled = True
        End If
    End Sub

    Private Sub UpdateProgress()
        If Me.InvokeRequired Then
            Me.Invoke(Sub() UpdateProgress())
        Else
            MetroProgressBar1.Value += 1
            MetroProgressBar1.Refresh()
        End If
    End Sub
End Class

参考文献:

MrGadget 让我朝着正确的方向前进,但它只删除文件而不是 folders/sub-folders 并且它也不会删除具有 super-large 文件名的文件,这就是我使用的原因AlphaFS 文件系统。这是 MrGadgets 修改后的代码,我添加了一个计时器和标签。 Label1 = FilesCount 所以当它达到 0 时,计时器将调用删除根文件夹和所有 sub-folders.

click here for image of form

Imports System
Imports System.Text.RegularExpressions
Imports Alphaleonis
Imports Alphaleonis.Win32.Filesystem
Imports System.ComponentModel
Imports System.IO

Public Class Form1    
Private FilesList As IEnumerable(Of String)

Private Sub Button6_Click(sender As Object, e As EventArgs)
    Button1.Enabled = False
    Timer1.Enabled = True

    ' Capture list of all files in all subfolders
    FilesList = Alphaleonis.Win32.Filesystem.Directory.EnumerateFiles(Alphaleonis.Win32.Filesystem.Path.Combine(My.Settings.AgencyDataPath, MetroTextBox1.Text), "*", SearchOption.AllDirectories)

    ' Add FileCount to Label1
    Label1.Text = FilesList.Count

    ' Initialize ProgressBar
    MetroProgressBar1.Value = 0
    MetroProgressBar1.Maximum = FilesList.Count

    ' Execute DeleteFilesFS in separate thread
    Task.Run(Sub() DeleteFilesFS())
End Sub

Private Sub DeleteFilesFS()

    Dim orderFolder As String
    orderFolder = My.Settings.AgencyDataPath & "\" & MetroTextBox1.Text
    MsgBox(orderFolder)

    For Each Filename As String In FilesList
        Alphaleonis.Win32.Filesystem.File.Delete(Filename)
        ListBox1.Items.Add("-->  Deleting: " & orderFolder)

        UpdateProgress()
    Next

    If Me.InvokeRequired Then
        Me.Invoke(Sub() Button1.Enabled = True)
    Else
        Button1.Enabled = True
    End If

    If Label1.Text = 0 Then
        Alphaleonis.Win32.Filesystem.Directory.Delete(orderFolder, True)
        ListBox1.Items.Add("-->  Finished Deleting: " & orderFolder)
    End If

End Sub
Private Sub DeleteFiles()

    For Each Filename As String In FilesList
        Alphaleonis.Win32.Filesystem.File.Delete(Filename)

        UpdateProgress()
    Next

    If Me.InvokeRequired Then
        Me.Invoke(Sub() Button1.Enabled = True)
    Else
        Button1.Enabled = True
    End If


End Sub

Private Sub UpdateProgress()
    If Me.InvokeRequired Then
        Me.Invoke(Sub() UpdateProgress())
    Else
        MetroProgressBar1.Value += 1
        MetroProgressBar1.Refresh()
    End If
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim orderFolder As String
    orderFolder = My.Settings.AgencyDataPath & "\" & MetroTextBox1.Text
    Button1.Enabled = False
    Timer1.Enabled = True
    ListBox1.Items.Add("-->  Started Deleting: " & orderFolder)

    ' Capture list of all files in all subfolders
    FilesList = Alphaleonis.Win32.Filesystem.Directory.EnumerateFiles(Alphaleonis.Win32.Filesystem.Path.Combine(My.Settings.AgencyDataPath, MetroTextBox1.Text), "*", SearchOption.AllDirectories)

    ' Add FileCount to Label1
    Label1.Text = FilesList.Count

    ' Initialize ProgressBar
    MetroProgressBar1.Value = 0
    MetroProgressBar1.Maximum = FilesList.Count

    ' Execute DeleteFiles in separate thread
    Task.Run(Sub() DeleteFiles())
End Sub

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Dim orderFolder As String
    orderFolder = My.Settings.AgencyDataPath & "\" & MetroTextBox1.Text


    Label1.Text = FilesList.Count

    If Label1.Text = "0" Then
        Alphaleonis.Win32.Filesystem.Directory.Delete(orderFolder, True)
        ListBox1.Items.Add("-->  Finished Deleting: " & orderFolder)
        Timer1.Enabled = False
    End If

End Sub

End Class

由于来自 OP 的更多信息已经曝光,并且由于 OP 要求对他们发布的答案代码提出建议,我提供以下内容。不需要计时器,减少了导入并说明了原因,简化了代码。

Imports System.Threading.Tasks
Imports System.Collections.Generic
Imports System.Linq
Imports Alphaleonis.Win32.Filesystem

' Do not import System.IO to ensure avoidance of namespace conflict / confusion
' Specify IO. in the code where it's needed for IO.SearchOptions (2 places)
' Any File / Directory methods called below are Alphaleonis unless IO is specified

Public Class Form1
    Private FilesList As List(Of String)
    Private orderFolder As String = String.Empty

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        orderFolder = Path.Combine(My.Settings.AgencyDataPath, MetroTextBox1.Text)

        Button1.Enabled = False
        ListBox1.Items.Add("-->  Started Deleting: " & orderFolder)

        ' Capture list of all files in all subfolders
        FilesList = Directory.EnumerateFiles(orderFolder, "*", IO.SearchOption.AllDirectories, PathFormat.LongFullPath).ToList

        ' Initialize Label1 with FileCount
        Label1.Text = FilesList.Count.ToString

        ' Initialize ProgressBar
        MetroProgressBar1.Value = 0
        MetroProgressBar1.Maximum = FilesList.Count

        ' Execute DeleteFiles in separate thread
        Task.Run(Sub() DeleteFiles())
    End Sub

    Private Sub DeleteFiles()
        ' Delete all files in all folders
        For Each Filename As String In FilesList
            File.Delete(Filename, False, PathFormat.LongFullPath)
            UpdateProgress()
        Next

        ' Remove the now empty folder structure
        Directory.Delete(orderFolder, True)

        FinishProgress()
    End Sub

    Private Sub UpdateProgress()
        If Me.InvokeRequired Then
            Me.Invoke(Sub() UpdateProgress())
        Else
            MetroProgressBar1.Value += 1
            MetroProgressBar1.Refresh()

            Label1.Text = (FilesList.Count - MetroProgressBar1.Value).ToString
            Label1.Refresh()
        End If
    End Sub

    Private Sub FinishProgress()
        If Me.InvokeRequired Then
            Me.Invoke(Sub() FinishProgress())
        Else
            ListBox1.Items.Add("-->  Finished Deleting: " & orderFolder)
            Button1.Enabled = True
        End If
    End Sub
End Class