I am trying to clear session cookies in a WPF WebBrowser. This method
Public Const INTERNET_OPTION_END_BROWSER_SESSION As Integer = 42
<DllImport("wininet.dll", SetLastError:=True)>
Public Function InternetSetOption(ByVal hInternet As IntPtr, ByVal dwOption As Integer, ByVal lpBuffer As IntPtr, ByVal lpdwBufferLength As Integer) As Boolean
End Function
described here How to clear System.Windows.Forms.WebBrowser session data? works for our WinForms applications, but not for WPF.
Any ideas?
Thanks
Turns out the answer is to ensure that the WebBrowser object is created each time the page is loaded.
As the WebBrowser object is not considered to be a control I created a ScrollViewer at initialisation then added the WebBrowser to the ScrollViewer on the loaded event.
It now works perfectly
for Faber75
Imports System.ComponentModel
Class Website_Login_Page
Private LoginBrowser As WebBrowser
Private Sub Website_Login_Page_Initialized(sender As Object, e As System.EventArgs) Handles Me.Initialized
Try
Website_Login_Grid.Background = New SolidColorBrush(Colors.White)
For i As Integer = 0 To 1
Dim vRow As New RowDefinition
If i = 0 Then
vRow.Height = New GridLength(35, GridUnitType.Star)
Else
vRow.Height = New GridLength(35)
End If
Website_Login_Grid.RowDefinitions.Add(vRow)
Next
Dim SV As New ScrollViewer
With SV
.VerticalScrollBarVisibility = ScrollBarVisibility.Auto
.Name = "Website_Login_SV"
End With
RegisterControl(Website_Login_Grid, SV)
'Cookies are not removed if the WebBrowser object is not created each time the page is loaded!
' LoginBrowser = New WebBrowser
Grid.SetRow(SV, 0)
Website_Login_Grid.Children.Add(SV)
Dim DP As DockPanel = PageStatusBarDP(Website_Login_Grid)
Grid.SetRow(DP, 1)
Website_Login_Grid.Children.Add(DP)
Catch ex As Exception
EmailError(ex)
End Try
End Sub
Private Sub Website_Login_Page_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
Try
If LoginBrowser Is Nothing Then
LoginBrowser = New WebBrowser
End If
Dim SV As ScrollViewer = Website_Login_Grid.FindName("Website_Login_SV")
SV.Content = LoginBrowser
AddHandler LoginBrowser.Navigating, AddressOf WebBrowser_Loading
AddHandler LoginBrowser.LoadCompleted, AddressOf WebBrowser_Loaded
AddHandler LoginBrowser.Navigated, AddressOf WebBrowser_Navigated
If InternetSetOption(IntPtr.Zero, INTERNET_OPTION_END_BROWSER_SESSION, IntPtr.Zero, 0) = False Then
MessageBox.Show("Returned False")
End If
With LoginBrowser
.Navigate(New Uri("https://website.com"))
End With
Catch ex As Exception
EmailError(ex)
End Try
End Sub
Private Sub Website_Login_Page_Unloaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Unloaded
Try
If Not LoginBrowser Is Nothing Then
RemoveHandler LoginBrowser.Navigating, AddressOf WebBrowser_Loading
RemoveHandler LoginBrowser.LoadCompleted, AddressOf WebBrowser_Loaded
RemoveHandler LoginBrowser.Navigated, AddressOf WebBrowser_Navigated
LoginBrowser = Nothing
End If
GC.GetTotalMemory(True)
Catch ex As Exception
EmailError(ex)
End Try
End Sub
Private Sub WebBrowser_Loading(ByVal sender As Object, ByVal e As NavigatingCancelEventArgs)
PageStatusBarLoading(Website_Login_Grid)
PageStatusBarRightChangeText(Website_Login_Grid, "Loading... Please wait...")
End Sub
Private Sub WebBrowser_Loaded(ByVal sender As Object, ByVal e As NavigationEventArgs)
Dim vDoc As Object = LoginBrowser.Document
Dim vTitle As String = vDoc.Title
PageStatusBarLoaded(Website_Login_Grid, vTitle)
PageStatusBarRightChangeText(Website_Login_Grid, "Loaded")
End Sub
Private Sub WebBrowser_Navigated(ByVal sender As Object, ByVal e As NavigationEventArgs)
Dim vDoc As Object = LoginBrowser.Document
Dim vTitle As String = vDoc.Title
PageStatusBarLoaded(Website_Login_Grid, vTitle)
PageStatusBarRightChangeText(Website_Login_Grid, "Loaded")
End Sub
End Class
Related
Im trying to do a login system where I store the credentials and a desired profile pic image on an access database. the desired result is that when the login matches form 1 closes and opens form 2 with the saved image loaded on a corner.
i tried doing this
Form 1 code:
Imports System.Data.OleDb
Imports System.IO
Public Class Form1
Private PictureFormat As String
Private Sub FillPictureBoxFromFile()
With OpenFileDialog1
.Filter = "(*.jpg)|*.jpg|(*.png)|*.png"
.RestoreDirectory = True
.Title = "Select a file to open"
If .ShowDialog = DialogResult.OK Then
PictureBox1.Image = Image.FromFile(OpenFileDialog1.FileName)
End If
PictureFormat = Path.GetExtension(OpenFileDialog1.FileName)
End With
End Sub
Private cnStr As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\geral\source\repos\Login Fase 3 Final\Login Fase 3 Final\bin\Release\DBLoginPic.mdb"
Private Sub saveimage()
Dim arrimage() As Byte
Using mstream As New System.IO.MemoryStream
If PictureFormat.ToLower = ".png" Then
PictureBox1.Image.Save(mstream, System.Drawing.Imaging.ImageFormat.Png)
ElseIf PictureFormat.ToLower = ".jpg" Then
PictureBox1.Image.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg)
End If
arrimage = mstream.GetBuffer()
Dim Filesize As Long
Filesize = mstream.Length
End Using
Using con As New OleDbConnection(cnStr),
cmd As New OleDbCommand("Insert into TBLoginPic (Imagen) Values (#Imagen)", con)
With cmd
.Parameters.Add("#Imagen", OleDbType.Binary).Value = arrimage
'.Parameters.Add("#Nombre", OleDbType.VarChar).Value = TextBox1.Text
con.Open()
.ExecuteNonQuery()
End With
End Using
End Sub
Private Function GetDataByName(name As String) As DataTable
Dim dt As New DataTable
Using conn As New OleDb.OleDbConnection(cnStr),
cmd As New OleDbCommand("Select * from TBLoginPic where Usuario= #Buscar", conn)
cmd.Parameters.Add("#Buscar", OleDbType.VarChar).Value = TBusuario.Text
conn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
Private Sub Label2_Click(sender As Object, e As EventArgs) Handles Label2.Click
End Sub
Private Sub TBusuario_TextChanged(sender As Object, e As EventArgs) Handles TBusuario.TextChanged
End Sub
Private Sub TBcontraseña_TextChanged(sender As Object, e As EventArgs) Handles TBcontraseña.TextChanged
End Sub
Private Sub BtnLoguearse_Click(sender As Object, e As EventArgs) Handles BtnLoguearse.Click
If Me.TBLoginPicTableAdapter.BuscarDatos(Me.DBLoginPicDataSet.TBLoginPic, TBusuario.Text, TBcontraseña.Text) Then
Dim dt As DataTable
Try
dt = GetDataByName(TBusuario.Text)
Catch ex As Exception
MessageBox.Show(ex.Message)
Exit Sub
End Try
TBusuario.Text = dt(0)("Usuario").ToString
Dim arrimage = DirectCast(dt(0)("Imagen"), Byte())
Dim mstream As New System.IO.MemoryStream(arrimage)
PictureBox1.Image = Image.FromStream(mstream)
Form2.Show()
_selectedImage = PictureBox1.Image
Me.Close()
Else
MsgBox("Datos Erroneos")
End If
End Sub
Private Sub BtnRegistrarse_Click(sender As Object, e As EventArgs) Handles BtnRegistrarse.Click
Me.TBLoginPicBindingSource.AddNew()
Me.TBLoginPicBindingSource.EndEdit()
Me.TBLoginPicTableAdapter.Update(Me.DBLoginPicDataSet)
Try
saveimage()
Catch ex As Exception
MessageBox.Show(ex.Message)
Exit Sub
End Try
MsgBox("Image has been saved in the database")
End Sub
Private Sub BtnExaminar_Click(sender As Object, e As EventArgs) Handles BtnExaminar.Click
FillPictureBoxFromFile()
End Sub
Private Sub PictureBox1_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'DBLoginPicDataSet.TBLoginPic' table. You can move, or remove it, as needed.
Me.TBLoginPicTableAdapter.Fill(Me.DBLoginPicDataSet.TBLoginPic)
End Sub
Private Sub TBLoginPicBindingNavigatorSaveItem_Click(sender As Object, e As EventArgs)
Me.Validate()
Me.TBLoginPicBindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.DBLoginPicDataSet)
End Sub
End Class
Form 2 Code:
Module imagen
Public _selectedImage As Image
Public ReadOnly Property SelectedImage As Image
Get
Return _selectedImage
End Get
End Property
End Module
Public Class Form2
Private Sub TBLoginPicBindingNavigatorSaveItem_Click(sender As Object, e As EventArgs)
Me.Validate()
Me.TBLoginPicBindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.DBLoginPicDataSet)
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'DBLoginPicDataSet.TBLoginPic' table. You can move, or remove it, as needed.
Me.TBLoginPicTableAdapter.Fill(Me.DBLoginPicDataSet.TBLoginPic)
_selectedImage = PBPerfil.Image
End Sub
Public Sub PBPerfil_Click(sender As Object, e As EventArgs) Handles PBPerfil.Click
End Sub
End Class
and get this error
System.InvalidCastException: 'Unable to cast object of type 'System.DBNull' to type 'System.Byte[]'.'
This is how form 1 looks like
This is how form 2 looks like
This is how my database looks like (don't worry there is not any personal info here))
This is where I try to send it from form 1 to 2
This is how I'm trying to receive it on form 2
any tips on what I could do better?
You need to check for nulls. If there is no data in the image column it will error when you try to manipulate it. I would suggest that you selected a default image to display if none is present in the database.
If dt(0)("Usuario") IsNot Nothing OrElse Not IsDBNull(dt(0)("Usuario")) Then
TBusuario.Text = dt(0)("Usuario").ToString
Dim arrimage = DirectCast(dt(0)("Imagen"), Byte())
Dim mstream As New System.IO.MemoryStream(arrimage)
PictureBox1.Image = Image.FromStream(mstream)
Else
PictureBox1.Image = Image.FromFile("DefaultImage.png")
End If
I'm new to WPF and the whole threading format. I'm pretty sure I'm close to getting this correct, however, I'm getting the error. "The calling thread cannot access this object because a different thread owns it." I was getting this error before and i had to add the "Dispatcher.BeginInvoke(Sub() LoadLoad())" line, but I'm still getting the error. When i get the error, it highlights the line "Dim dc = New VSCSystemEntities1" in the LoadLoad() sub method. Any help would be appreciated. Thanks.
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
InitialLoad()
End Sub
Private Sub InitialLoad()
Try
loadPayeeTransactionAccounts()
bw.WorkerSupportsCancellation = True
bw.WorkerReportsProgress = True
AddHandler bw.DoWork, AddressOf bw_DoWork
AddHandler bw.ProgressChanged, AddressOf bw_ProgressChanged
AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted
Catch ex As Exception
MessageBox.Show(ex.Message, "Atlas Error while Loading", MessageBoxButton.OK, MessageBoxImage.Error)
Finally
End Try
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
LoadLoad()
End Sub
Private Sub LoadLoad()
Dispatcher.BeginInvoke(Sub() LoadLoad())
txtSearch.Text = ""
Dim dc = New VSCSystemEntities1
Dim ContainsSearch = New List(Of tblActgPayeeTransactionAccounts2)
Try
ContainsSearch = (From z In dc.tblActgPayeeTransactionAccounts2 Select z Where z.intActgAcctID <> 236).ToList
For Each item In (ContainsSearch)
For i = 1 To ContainsSearch.Count
aList.add(New PayeeTransactions() With {.AccountingAccountID = item.intActgAcctID, .ProgramCode = item.chrPgmCode, _
.CarrierCode = item.intCarrierCode, .DealerNumber = item.chrDlrNum, _
.CoverageCode = item.chrCvgCode, .PayeeType = item.chrPayeeType, .FeeType = item.chrFeeType, .PayeeCode = item.intPayeeCode.ToString, _
.TransactionType = item.chrTransType, .AccountID = item.inbAcctgID, _
.CarrierDescription = item.chrCarrierDesc, .CarrierDescriptionShort = item.chrCarrierDescSht, _
.AccountCustomerID = item.intAcctCustID.ToString, .AccountCode = item.intAcctCo, _
.AccountCodeReceived = item.intAcctCoRec})
System.Threading.Thread.Sleep(200)
bw.ReportProgress(i)
Next
Next
lblCount.Content = ContainsSearch.Count()
dGrid.ItemsSource = Nothing
_ContainsText = CollectionViewSource.GetDefaultView(aList)
dGrid.ItemsSource = _ContainsText
Catch ex As Exception
Throw New Exception("Error: " & ex.Message)
Finally
dc.Dispose()
End Try
End Sub
Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
Me.tbProgress.Text = e.ProgressPercentage.ToString() & "%"
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
If e.Cancelled = True Then
Me.tbProgress.Text = "Canceled!"
ElseIf e.Error IsNot Nothing Then
Me.tbProgress.Text = "Error: " & e.Error.Message
Else
Me.tbProgress.Text = "Done!"
End If
End Sub
Private Sub btnRefresh_Click(sender As Object, e As RoutedEventArgs) Handles btnRefresh.Click
If Not bw.IsBusy = True Then
bw.RunWorkerAsync()
End If
End Sub
I am developing a WinForms application and I want a ListBox (or a control which provides list of strings) such that when the user hovers the mouse over an item it will show a delete sign for that particular item.
Is there any control available for WinForms to do this?
Setting the ListBox DrawMode to OwnerDrawFixed (or OwnerDrawVariable), you can just handle this yourself with the Mouse events:
Public Class Form1
Private _MouseIndex As Integer = -1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
ListBox1.Items.Add("String #1")
ListBox1.Items.Add("String #2")
End Sub
Private Sub ListBox1_DrawItem(ByVal sender As Object, ByVal e As DrawItemEventArgs) Handles ListBox1.DrawItem
e.DrawBackground()
If e.Index > -1 Then
Dim brush As Brush = SystemBrushes.WindowText
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
brush = SystemBrushes.HighlightText
End If
e.Graphics.DrawString(ListBox1.Items(e.Index), e.Font, brush, e.Bounds.Left + 20, e.Bounds.Top)
If e.Index = _MouseIndex Then
e.Graphics.DrawString("X", e.Font, brush, e.Bounds.Left + 2, e.Bounds.Top)
End If
End If
End Sub
Private Sub ListBox1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles ListBox1.MouseDown
If _MouseIndex > -1 AndAlso ListBox1.IndexFromPoint(e.Location) = _MouseIndex AndAlso e.Location.X < 20 Then
Dim index As Integer = _MouseIndex
If MessageBox.Show("Do you want to delete this item?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
ListBox1.Items.RemoveAt(index)
ListBox1.Invalidate()
End If
End If
End Sub
Private Sub ListBox1_MouseLeave(ByVal sender As Object, ByVal e As EventArgs) Handles ListBox1.MouseLeave
If _MouseIndex <> -1 Then
_MouseIndex = -1
ListBox1.Invalidate()
End If
End Sub
Private Sub ListBox1_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles ListBox1.MouseMove
Dim index As Integer = ListBox1.IndexFromPoint(e.Location)
If index <> _MouseIndex Then
_MouseIndex = index
ListBox1.Invalidate()
End If
End Sub
End Class
Refactor as needed.
I want, that if a cell/row goes to edit mode, then, if the user attempts to select a different row, it should try to commit that row, if the row is not committed sucessfully, it should decline the selection request and the editing row should remain selected and in edit mode.
Do you have experience with a good helper for it? any good workaround?
NOTE: I've been struggling with this issue for a long time and already got some experience, so please post only working examples, not random thoughts.
The code bellow is includes extension from here (code normalized to fit StackOverflow screen witdh, sorry).
Imports System.ComponentModel
Imports System.Windows.Threading
Namespace Components
Public NotInheritable Class DataGridSelectionChangingBehavior
Public Shared Function GetEnableSelectionChanging(
ByVal element As DataGrid) As Boolean
If element Is Nothing Then Throw New ArgumentNullException("element")
Return element.GetValue(EnableSelectionChangingProperty)
End Function
Public Shared Sub SetEnableSelectionChanging(
ByVal element As DataGrid, ByVal value As Boolean)
If element Is Nothing Then Throw New ArgumentNullException("element")
element.SetValue(EnableSelectionChangingProperty, value)
End Sub
Public Shared ReadOnly EnableSelectionChangingProperty As _
DependencyProperty =
DependencyProperty.RegisterAttached("EnableSelectionChanging",
GetType(Boolean),
GetType(DataGridSelectionChangingBehavior),
New FrameworkPropertyMetadata(False,
New PropertyChangedCallback(
AddressOf EnableSelectionChanging_PropertyChanged)))
Public Shared Sub AddSelectionChangingHandler(
ByVal element As DataGrid, handler As SelectionChangingEventHandler)
If element IsNot Nothing Then _
element.AddHandler(
DataGridSelectionChangingBehavior.SelectionChangingEvent, handler)
End Sub
Public Shared Sub RemoveSelectionChangingHandler(
ByVal element As DataGrid, handler As SelectionChangingEventHandler)
If element IsNot Nothing Then _
element.RemoveHandler(
DataGridSelectionChangingBehavior.SelectionChangingEvent, handler)
End Sub
Public Shared ReadOnly SelectionChangingEvent As RoutedEvent =
EventManager.RegisterRoutedEvent("SelectionChanging",
RoutingStrategy.Bubble,
GetType(SelectionChangingEventHandler),
GetType(DataGridSelectionChangingBehavior))
Private Shared Sub EnableSelectionChanging_PropertyChanged(
ByVal sender As Object, ByVal e As DependencyPropertyChangedEventArgs)
Dim dataGrid = DirectCast(sender, DataGrid)
If CBool(e.NewValue) Then
AddHandler dataGrid.PreparingCellForEdit,
AddressOf DataGrid_PreparingCellForEdit
AddHandler dataGrid.SelectionChanged,
AddressOf DataGrid_SelectionChanged
Else
RemoveHandler dataGrid.PreparingCellForEdit,
AddressOf DataGrid_PreparingCellForEdit
RemoveHandler dataGrid.SelectionChanged,
AddressOf DataGrid_SelectionChanged
RecentColumn.Remove(dataGrid)
End If
End Sub
Private Shared Sub DataGrid_SelectionChanged(
ByVal sender As Object, ByVal e As SelectionChangedEventArgs)
If e.RemovedItems.Count = 0 Then Exit Sub
Dim dataGrid = DirectCast(sender, DataGrid)
Dim removed = e.RemovedItems(0)
Dim row = dataGrid.GetContainerFromItem(Of DataGridRow)(removed)
Dim scea As New SelectionChangingEventArgs(row,
DataGridSelectionChangingBehavior.SelectionChangingEvent, dataGrid)
dataGrid.RaiseEvent(scea)
If scea.Cancel Then
RemoveHandler dataGrid.SelectionChanged,
AddressOf DataGrid_SelectionChanged
Dim operation = dataGrid.Dispatcher.BeginInvoke(
Sub()
dataGrid.SelectedItem = removed
Dim column As DataGridColumn = Nothing
If RecentColumn.TryGetValue(dataGrid, column) Then
Dim cellsPanel =
row.GetVisualDescendant(Of DataGridCellsPanel)().
Children.Cast(Of DataGridCell)()
Dim recentCell =
If(cellsPanel.SingleOrDefault(
Function(cell) cell.Column Is column),
cellsPanel.FirstOrDefault)
If recentCell IsNot Nothing Then
recentCell.IsEditing = True
Keyboard.Focus(recentCell)
End If
End If
End Sub,
DispatcherPriority.ContextIdle)
AddHandler operation.Completed,
Sub(s, ea) AddHandler dataGrid.SelectionChanged,
AddressOf DataGrid_SelectionChanged
End If
End Sub
Private Shared m_RecentColumn As Dictionary(Of DataGrid, DataGridColumn)
Public Shared ReadOnly Property RecentColumn() As Dictionary(Of DataGrid,
DataGridColumn)
Get
If m_RecentColumn Is Nothing Then m_RecentColumn =
New Dictionary(Of DataGrid, DataGridColumn)()
Return m_RecentColumn
End Get
End Property
Private Shared Sub DataGrid_PreparingCellForEdit(
ByVal sender As Object, e As DataGridPreparingCellForEditEventArgs)
Dim dataGrid = DirectCast(sender, DataGrid)
RecentColumn(dataGrid) = e.Column
End Sub
End Class
Public Delegate Sub SelectionChangingEventHandler(
ByVal sender As Object, ByVal e As SelectionChangingEventArgs)
Public Class SelectionChangingEventArgs : Inherits RoutedEventArgs
Public Sub New(ByVal row As DataGridRow, routedEvent As RoutedEvent)
MyBase.New(routedEvent)
m_CurrentRow = row
End Sub
Public Sub New(ByVal row As DataGridRow,
ByVal routedEvent As RoutedEvent,
ByVal source As Object)
MyBase.New(routedEvent, source)
m_CurrentRow = row
End Sub
Private m_CurrentRow As DataGridRow
Public ReadOnly Property CurrentRow() As DataGridRow
Get
Return m_CurrentRow
End Get
End Property
Public ReadOnly Property Item() As Object
Get
If CurrentRow IsNot Nothing Then Return CurrentRow.Item
Return Nothing
End Get
End Property
Public Property Cancel As Boolean
End Class
End Namespace
Usage:
<DataGrid Name="dg"
src:DataGridSelectionChangingBehavior.EnableSelectionChanging="True"
src:DataGridSelectionChangingBehavior.SelectionChanging="dg_SelectionChanging">
Code behind (pseudu):
Private Sub dg_SelectionChanging(ByVal sender As Object,
ByVal e As SelectionChangingEventArgs)
If e.CurrentRow.IsEditing Then
Dim item = TryCast(e.CurrentRow.Item, MyEntityType)
If item IsNot Nothing AndAlso item.IsValid Then
Dim dataGrid = DirectCast(sender, DataGrid)
Dim committed = dataGrid.CommitEdit(DataGridEditingUnit.Row, True)
If committed Then Exit Sub
End If
e.Cancel = True
End If
End Sub
Note: visual studio might not show the event in the intellisense and might even generate a design-time error, but it should compile and work perfect.
FYI: code formatted modified to fit SO screen.
What's wrong in my code? It's not updating the TextBox and the ProgressBar while deleting files.
Imports System.Windows.Threading
Imports System.IO
Class MainWindow
Private Sub bt_Click(ByVal sender As Object,
ByVal e As RoutedEventArgs) Handles bt.Click
Dim sb As New System.Text.StringBuilder
Dim files = IO.Directory.EnumerateFiles(
My.Computer.FileSystem.SpecialDirectories.Temp, "*.*",
SearchOption.TopDirectoryOnly)
Dim count = files.Count
pb.Minimum = 0
pb.Maximum = count
For i = 0 To count - 1
Dim f = files(i)
Dispatcher.BeginInvoke(
New Action(Of String, Integer)(
Sub(str, int)
tb.SetValue(TextBox.TextProperty, str)
pb.SetValue(ProgressBar.ValueProperty, int)
End Sub),
DispatcherPriority.Send,
f, i + 1)
Try
File.Delete(f)
Catch ex As Exception
sb.AppendLine(f)
End Try
Dim exceptions = sb.ToString
Stop
Next
End Sub
End Class
I got this working with the BackgroundWorker object. This places your work in a background thread, with calls to update the UI going through the ProgressChanged event. I also used Invoke instead of BeginInvoke within the work loop, which forces the loop to wait for the UI to become updated before it proceeds.
Imports System.ComponentModel
Imports System.IO
Class MainWindow
Private WithEvents bw As New BackgroundWorker
Private Sub Button1_Click(ByVal sender As System.Object,
ByVal e As RoutedEventArgs) Handles btn.Click
pb.Minimum = 0
pb.Maximum = 100
bw.WorkerReportsProgress = True
bw.RunWorkerAsync()
End Sub
Private Sub bw_DoWork(ByVal sender As Object,
ByVal e As DoWorkEventArgs) Handles bw.DoWork
Dim sb As New System.Text.StringBuilder
Dim files = IO.Directory.EnumerateFiles(
My.Computer.FileSystem.SpecialDirectories.Temp, "*.*",
SearchOption.TopDirectoryOnly)
Dim count = files.Count
Me.Dispatcher.BeginInvoke(Sub()
tb.Text = "SOMETHING ELSE"
End Sub)
For i = 0 To count - 1
Dim f = files(i)
Dim myI = i + 1
Me.Dispatcher.Invoke(
Sub()
bw.ReportProgress(CInt((myI / count) * 100), f)
End Sub)
'Try
' File.Delete(f)
'Catch ex As Exception
' sb.AppendLine(f)
'End Try
Dim exceptions = sb.ToString
'Stop
Next
End Sub
Private Sub bw_ProgressChanged(
ByVal sender As Object,
ByVal e As ProgressChangedEventArgs) Handles bw.ProgressChanged
Dim fString As String = TryCast(e.UserState, String)
Me.Dispatcher.BeginInvoke(Sub()
tb.Text = fString
End Sub)
End Sub
End Class