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
所以我创建了一个 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