Add event to FileSystemWatcher when property EnableRaisingEvents changed - vb.net

I have created a custom class
Public Class MyFSW
Inherits FileSystemWatcher
Public Property ParentForm As Form
Public Property TabPage As TabPage
End Class
Now I want to add a custom event to the this class, that fires when the property "EnableRaisingEvents" of the FileSystemWatcher changes?
Is there any chance to do this?

The EnableRaisingEvents property is not declared Overridable so you can't override it. You can shadow it though:
Public Class FileSystemWatcherEx
Inherits FileSystemWatcher
Public Property ParentForm As Form
Public Property TabPage As TabPage
Public Shadows Property EnableRaisingEvents As Boolean
Get
Return MyBase.EnableRaisingEvents
End Get
Set(value As Boolean)
If MyBase.EnableRaisingEvents <> value Then
MyBase.EnableRaisingEvents = value
OnEnableRaisingEventsChanged(EventArgs.Empty)
End If
End Set
End Property
Public Event EnableRaisingEventsChanged As EventHandler
Protected Overridable Sub OnEnableRaisingEventsChanged(e As EventArgs)
RaiseEvent EnableRaisingEventsChanged(Me, e)
End Sub
End Class
That will work as long as you set the property through a reference of type FileSystemWatcherEx. Because the property is shadowed rather than overridden, setting it through a reference of type FileSystemWatcher will bypass the derived property implementation and the event will not be raised. You really can't do anything about that.

Thank you so far!
This is what I got now (in my class-file):
Public Class MyFSW
Inherits FileSystemWatcher
Public Property ParentForm As Form
Public Property TabPage As TabPage
Public Shadows Property EnableRaisingEvents As Boolean
Get
Return MyBase.EnableRaisingEvents
End Get
Set(value As Boolean)
If MyBase.EnableRaisingEvents <> value Then
MyBase.EnableRaisingEvents = value
OnEnableRaisingEventsChanged(EventArgs.Empty)
End If
End Set
End Property
Public Event EnableRaisingEventsChanged As EventHandler
Protected Overridable Sub OnEnableRaisingEventsChanged(e As EventArgs)
RaiseEvent EnableRaisingEventsChanged(Me, e)
End Sub
End Class
In my Form-Class is got this:
Sub CreateFSW()
w.Watcher = New MyFSW With {
.ParentForm = f,
.TabPage = tp,
.Path = w.Path,
.Filter = w.Filter,
.IncludeSubdirectories = w.IncludeSubdirs,
.NotifyFilter = DirectCast(w.NotifyFilter, NotifyFilters)
}
AddHandler w.Watcher.Created, AddressOf Fsw_EventRaise
AddHandler w.Watcher.Changed, AddressOf Fsw_EventRaise
AddHandler w.Watcher.Renamed, AddressOf Fsw_EventRaise
AddHandler w.Watcher.Deleted, AddressOf Fsw_EventRaise
AddHandler w.Watcher.EnableRaisingEventsChanged, AddressOf Fsw_Event
End Sub
Private Sub Fsw_Event(sender As Object, e As FileSystemEventArgs)
MessageBox.Show("Works")
End Sub
The compiler says:
Option Strict On does not allow narrowing in implicit type conversions between method Fsw_Event(sender As Object, e As FileSystemEventArgs) and delegate Delegate Sub EventHandler(sender As Object, e As EventArgs)
Seems that some types does not match. I tried to change FileSystemEventArgs to EventArgs and stuff like this, but without luck.

As a continuation of a “previous example” you can achieve that with some small changes like the example below shows:
In this example the property is changed by clicking a button, but you can implement handlers on your own needs.
Option Strict On
Imports System.IO
Public Class Form1
Private Fsw As CustomFSW
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CreateFSW()
End Sub
Sub CreateFSW()
Fsw = New CustomFSW With {
.Name = "Tab1", 'Adding this you can specify the object is sending the event
.Path = "C:\Users\UserName\Desktop\Test\",
.Filter = "*.*",
.IncludeSubdirectories = True,
.EnableRaisingEvents = True
}
AddHandler Fsw.Created, AddressOf Fsw_Event
AddHandler Fsw.Changed, AddressOf Fsw_Event
AddHandler Fsw.Renamed, AddressOf Fsw_Event
AddHandler Fsw.Deleted, AddressOf Fsw_Event
'Here the handler of your custom event
AddHandler Fsw.MyCutomEvent, AddressOf Fsw_CutomEvent
End Sub
Private Class CustomFSW
Inherits FileSystemWatcher
Private counter As Integer = 0
Public Property Name As String
'You can use the base property instead of this for specific needs
Private _EnableRaisingEvents As Boolean
Public Overloads Property EnableRaisingEvents As Boolean
Get
Return _EnableRaisingEvents
End Get
Set(value As Boolean)
If Not value = _EnableRaisingEvents Then
counter += 1
RaiseEvent MyCutomEvent(Me, "Ciaooo, EnableRaisingEvents is changed " & counter.ToString & " times")
End If
_EnableRaisingEvents = value
End Set
End Property
'Rename this on your needs
Public Event MyCustomEvent(sender As Object, e As String)
End Class
Private Sub Fsw_CustomEvent(sender As Object, e As String)
' Do your stuff here
MsgBox(e)
End Sub
Private Sub Fsw_Event(sender As Object, e As FileSystemEventArgs)
Dim FSW As CustomFSW = CType(sender, CustomFSW)
If Not String.IsNullOrEmpty(FSW.Name) Then
Select Case FSW.Name
Case "Tab1"
'Do something
Debug.WriteLine("Event generated from: " & FSW.Name)
Case "Tab2"
'Do something else
Debug.WriteLine("Event generated from: " & FSW.Name)
End Select
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If Fsw IsNot Nothing Then
Fsw.EnableRaisingEvents = Not Fsw.EnableRaisingEvents
End If
End Sub
End Class

Related

How to Trigger button click from another form VB Net

I have three forms in total and i want to trigger one of the button on form 3 to be triggered automatically when form 1 loaded
Form 1
Public Class frmIOMain
' In This Form load I want to trigger the above mentioned button
Private Sub IOMain_Load(sender As Object, e As System.EventArgs) Handles Me.Load
' I want to Trigger the Above mentioned button here when my form is loaded
' But it is not working for me
frmUpdateDueDates.cmdUpdate_Click(Nothing, Nothing)
End Sub
End Class
Form 2
Public Class TestEquipmentManagement
Public EquipementTable As New DataTable("EquipmentTable")
Public EquiTypeSelection As String
Public EquiManufacturerSelection As String
Public EquiList_PK As New List(Of Integer)
Dim targetEquipmentList As New List(Of Model.equipment)
Private equipDB As Model.Entities = Nothing
Public Shared viewManager As ViewManager
Private equipment As New List(Of Model.equipment)
'Dim WithEvents excNewPFM As New VBACom
Public EquipCalTable As New DataTable("EquipCalTable")
Public Sub New()
Dim todayplusoneyear As Date
todayplusoneyear = Date.Today
todayplusoneyear = todayplusoneyear.AddYears(1)
'Assign current db
equipDB = frmIOMain.db
End Sub
End Class
Form 3
Public Class frmUpdateDueDates
Private EquipmentUpdates As UpdateCalibrationsViewModel
Private _success As Boolean = False
Public Sub New(db As Entities)
' Dieser Aufruf ist für den Designer erforderlich.
InitializeComponent()
EquipmentUpdates = New UpdateCalibrationsViewModel(db, New CAQ23(), False)
'Add Handlers
AddHandler EquipmentUpdates.OnProgressChanged, AddressOf progressChangedHandler
AddHandler EquipmentUpdates.OnInfotextChanged, AddressOf infoTextChangedHandler
prgUpdates.Maximum = EquipmentUpdates.intProgressMax
End Sub
Public Sub cmdUpdate_Click(sender As Object, e As EventArgs) Handles cmdUpdate.Click
cmdUpdate.Enabled = False
_success = EquipmentUpdates.startUpdating()
cmdCancel.Text = "Close"
End Sub
End Class
I want "cmdUpdate_Click" Button which is on form 3 to be triggered when my form 1 is loaded
Can Anyone tell me how i can do that?
Firstly, create an instance of the form, instead of using its default form instance. Calling a click handler across forms isn't a good idea. The handler may use the arguments sender As Object, e As EventArgs and from outside of the containing class, you can't assume you know that. Better practice would be to create a method which performs the click within the form, such as
Public Class frmUpdateDueDates
Public Sub cmdUpdateClick()
cmdUpdate.PerformClick()
End Sub
Private Sub cmdUpdate_Click(sender As Object, e As EventArgs) Handles cmdUpdate.Click
cmdUpdate.Enabled = False
_success = EquipmentUpdates.startUpdating()
cmdCancel.Text = "Close"
End Sub
End Class
Public Class frmIOMain
Private myFrmUpdateDueDates As frmUpdateDueDates
Private Sub IOMain_Load(sender As Object, e As System.EventArgs) Handles Me.Load
myFrmUpdateDueDates = New FrmUpdateDueDates()
myFrmUpdateDueDates.Show()
'myFrmUpdateDueDates.cmdUpdate_Click(Nothing, Nothing)
myFrmUpdateDueDates.cmdUpdateClick()
End Sub
End Class
And you can change the access modifier of the click handler back to Private
Even better would be to put the work into a different method which the click handler calls. Then the other form doesn't even need to know the button exists. Such as
Public Class frmUpdateDueDates
Public Sub DoUpdating()
cmdUpdate.Enabled = False
_success = EquipmentUpdates.startUpdating()
cmdCancel.Text = "Close"
End Sub
Private Sub cmdUpdate_Click(sender As Object, e As EventArgs) Handles cmdUpdate.Click
DoUpdating()
End Sub
End Class
Public Class frmIOMain
Private myFrmUpdateDueDates As frmUpdateDueDates
Private Sub IOMain_Load(sender As Object, e As System.EventArgs) Handles Me.Load
myFrmUpdateDueDates = New FrmUpdateDueDates()
myFrmUpdateDueDates.Show()
'myFrmUpdateDueDates.cmdUpdate_Click(Nothing, Nothing)
myFrmUpdateDueDates.DoUpdating()
End Sub
End Class

how to safe call a control from another thread using Timers.Timer

I read various posts, and made a practice project, but it does not works.
The form have a button and a text box with a default text 'Updated 0 times'. On button click starts the timer and each time update the text with the number of times the text was updated.
The exception of cross thread calls is not thrown, but when calling the text box, its .Text = "", the text is updated but not the text box on the form. And InvokeRequired is always false.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Here the textBox.Text = "Updated 0 times."
Dim checking_text As String = Me.TextBox1.Text
TimerTest.StartTimer()
End Sub
Delegate Sub UpdateTextInvoke(ByVal new_text As String)
Public Sub UpdateText(ByVal new_text As String)
'Here the textBox.Text = ""
Dim txtB As TextBox = Me.TextBox1
'InvokeRequired always = False.
If txtB.InvokeRequired Then
Dim invk As New UpdateTextInvoke(AddressOf UpdateText)
txtB.Invoke(invk, New Object() {new_text})
Else
'The value of this text box is updated, but the text on the form TextBox1 never changes
txtB.Text = new_text
End If
End Sub
End Class
Public Class TimerTest
Private Shared tmr As New System.Timers.Timer
Private Shared counter As Integer
Public Shared Sub StartTimer()
tmr.Interval = 5000
AddHandler tmr.Elapsed, AddressOf UdpateText
tmr.Enabled = True
End Sub
Public Shared Sub UdpateText(ByVal sender As Object, ByVal e As System.EventArgs)
counter += 1
Form1.UpdateText(String.Format("Updated {0} time(s).", counter))
End Sub
End Class
SOLVED
In the Class TimerTest added this code 'Private Shared myform As Form1 = Form1'
then changed 'Form1.UpdateText' To 'myform.UpdateText'
As indicated in the comments, you are using the default form instance feature of VB.Net. You could pass an instance of the form to the TimerTest class, and replace the reference to Form1 with the instance.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim checking_text As String = Me.TextBox1.Text
TimerTest.StartTimer(Me)
End Sub
Public Sub UpdateText(new_text As String)
If TextBox1.InvokeRequired Then
Dim invk As New Action(Of String)(AddressOf UpdateText)
TextBox1.Invoke(invk, {new_text})
Else
TextBox1.Text = new_text
End If
End Sub
End Class
Public Class TimerTest
Private Shared tmr As New System.Timers.Timer()
Private Shared counter As Integer
Private Shared instance As Form1
Public Shared Sub StartTimer(formInstance As Form1)
instance = formInstance
tmr.Interval = 5000
AddHandler tmr.Elapsed, AddressOf UdpateText
tmr.Enabled = True
End Sub
Public Shared Sub UdpateText(ByVal sender As Object, ByVal e As System.EventArgs)
counter += 1
instance.UpdateText(String.Format("Updated {0} time(s).", counter))
End Sub
End Class

Menu Item Custom Control Events

I am trying to create a menu list item that contains both a textbox and a label as a single item. In the code below I have made the necessary custom control class inherited from ToolStripControlHost and this looks and behaves as expected when created in the form menu.
The problem I am having is that the control's events are not firing the handler routine. In the example below, what I would expect to happen is that when the user types into the text box a message should show (other events have the same problem).
Thank you.
Control Classes:
Public Class ToolStripTextBoxWithLabel
Inherits ToolStripControlHost
Public Sub New(Optional ByVal lblText As String = "label")
MyBase.New(New ControlPanel(lblText))
End Sub
Public ReadOnly Property ControlPanelControl() As ControlPanel
Get
Return CType(Me.Control, ControlPanel)
End Get
End Property
End Class
Public Class ControlPanel
Inherits Panel
Friend WithEvents txt As New TextBox
Friend WithEvents lbl As New Label
Public Sub New(ByVal lblText As String)
Me.Height = 20
lbl.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Bottom
lbl.Text = lblText
lbl.TextAlign = ContentAlignment.BottomLeft
lbl.AutoSize = True
lbl.Height = Me.Height
lbl.Location = New Point(0, 3)
lbl.Parent = Me
txt.Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top
txt.Location = New Point(lbl.Right + 3, 0)
txt.Width = Me.Width - txt.Left
txt.Parent = Me
End Sub
End Class
Form Implementation:
Public Class Form1
Friend tb_SearchBox As ToolStripTextBoxWithLabel
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
tb_SearchBox = New ToolStripTextBoxWithLabel("Search:") With {.Name = "tb_SearchBox"}
AddHandler tb_SearchBox.TextChanged, AddressOf tb_SearchBox_TextChanged
Item1ToolStripMenuItem.DropDownItems.Add(tb_SearchBox)
End Sub
Private Sub tb_SearchBox_TextChanged(sender As Object, e As EventArgs)
MsgBox("Success")
End Sub
End Class
Using the TextChanged event of your ToolStripTextBoxWithLabel in this instance is inappropriate because that event should only be raised when the Text property of that object changes, which is not happening here. You need to do what Plutonix suggested but you should also do it with your own custom event rather than with the TextChanged event of the host, e.g.
Public Event TextBoxTextChanged As EventHandler
Protected Overridable Sub OnTextBoxTextChanged(e As EventArgs)
RaiseEvent TextBoxTextChanged(Me, e)
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
OnTextBoxTextChanged(EventArgs.Empty)
End Sub
Rather than deriving your ControlPanel class from Panel and creating the child controls in code, I would suggest that you create a user control and add the children in the designer. You would then use my answer below in two steps, i.e. the user control would handle the TextChanged event of the TextBox and then raise an event of its own that would, in turn, be handled by the ToolStripTextBoxWithLabel that would its own event.
Thanks to jmcilhinney and Plutonix I have put together the solution. For completeness and future community reference the full solution is below.
User Control:
Public Class CustomTextBox
Public Event TextBoxTextChanged As EventHandler
Protected Overridable Sub OnTextBoxTextChanged(e As EventArgs)
RaiseEvent TextBoxTextChanged(Me, e)
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
OnTextBoxTextChanged(EventArgs.Empty)
End Sub
Public Sub New (lblText as string)
InitializeComponent()
Caption = lblText
End Sub
Public Property Caption() As String
Get
Return Label1.Text
End Get
Set(ByVal value As String)
Label1.Text = value
End Set
End Property
Public Overrides Property Text() As String
Get
Return TextBox1.Text
End Get
Set(ByVal value As String)
TextBox1.Text = value
End Set
End Property
Public Class
Implementation:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim SearchBox As New CustomTextBox("Search")
Dim host As ToolStripControlHost = new ToolStripControlHost(windowNewMenu)
AddHandler SearchBox.TextBoxTextChanged, AddressOf SearchBox_TextChanged
ToolStripMenuItem1.DropDownItems.Add(host)
End Sub
Private Sub SearchBox_TextChanged(sender As Object, e As EventArgs)
MsgBox(sender.Text)
End Sub

Overriding a derived Event

I want to "override" an Event from a derived class - for example from a Forms-Control.
My actual state is, that the overriding (performed by the Command "Shadows") is working when I use the Handler of this Control directly.
Is the Control a member of a Collection it is only working with such Events which I have created by myself - if I try to use the overridden Event it isn't working. I suppose that the Collection uses the Event from the Base-Class.
Is that possible ?
And if "Yes" - what could I do ?
Code-Snippets from the described "Problem" :
This part collects the Event-Handler inside the Custom Control :
Private KalenderElemente As New Collection
Private Sub CreateElements()
KalenderElemente.Clear()
For i As Integer = 1 To 42
Dim myKalenderTag As New PP_Monatskalender_Tag
myKalenderTag.Name = "Tag_" + i.ToString("00")
myKalenderTag.ForeColor = my_ForeColor_Days
myKalenderTag.BackColor = my_BackColor_Days
myKalenderTag.Parent = Me
AddHandler myKalenderTag.Click, AddressOf KalenderTag_Click
AddHandler myKalenderTag.MouseMove, AddressOf KalenderTag_MouseMove
AddHandler myKalenderTag.MouseEnter, AddressOf KalenderTag_MouseEnter
AddHandler myKalenderTag.MouseLeave, AddressOf KalenderTag_MouseLeave
KalenderElemente.Add(myKalenderTag)
Next
End Sub
Private Sub Kalender_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseMove
If Not KalenderElemente.Item(0).Visible Then
KalenderElemente.Item(0).DatumsTag = 0
RaiseEvent MouseMove(KalenderElemente.Item(0), e)
Else
KalenderElemente.Item(41).DatumsTag = 0
RaiseEvent MouseMove(KalenderElemente.Item(41), e)
End If
End Sub
Private Sub KalenderTag_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
RaiseEvent MouseMove(sender, e)
End Sub
Shadows Event MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
Private Sub KalenderTag_MouseEnter(ByVal sender As Object, ByVal e As EventArgs)
RaiseEvent MouseEnter(sender, e)
End Sub
Shadows Event MouseEnter(ByVal sender As Object, ByVal e As EventArgs)
Private Sub KalenderTag_MouseLeave(ByVal sender As Object, ByVal e As EventArgs)
RaiseEvent MouseLeave(sender, e)
End Sub
Shadows Event MouseLeave(ByVal sender As Object, ByVal e As EventArgs)
Now each of the internal Controls deliver it's Mouse-Event to outside.
If I put it on a Form and write a script which takes the Event I could see that all works fine (and as expected).
In the following you see the part of the collection which should manage this Control (and others) :
Public Class MessageDefinition
Public WithEvents Control As Control
Public HeaderText As String
Public MessageText As String
Public DisplayShadow As Boolean
Public ToolTipLocation As ToolTipLocationDefintion
Public Location As Point
End Class
Public Class Message_Collection
Inherits CollectionBase
Public Shadows Sub Clear()
Dim myItem As MessageDefinition
For i As Integer = 1 To List.Count
myItem = List.Item(i - 1)
RemoveHandler myItem.Control.MouseEnter, AddressOf Item_MouseEnter
RemoveHandler myItem.Control.MouseMove, AddressOf Item_MouseMove
RemoveHandler myItem.Control.MouseLeave, AddressOf Item_MouseLeave
Next
List.Clear()
End Sub
Overrides Function ToString() As String
Return "[...]"
End Function
Public Sub Dispose()
Clear()
End Sub
' ================================
Public Sub SetMessage(item As MessageDefinition)
Dim myItem As MessageDefinition
For i As Integer = 1 To List.Count
myItem = List.Item(i - 1)
If myItem.Control.GetType Is item.Control.GetType _
AndAlso myItem.Control.Name = item.Control.Name Then
'List.Item(i - 1) = item
'RaiseEvent MouseEnter(item, System.EventArgs.Empty)
Exit Sub
End If
Next
AddHandler item.Control.MouseEnter, AddressOf Item_MouseEnter
AddHandler item.Control.MouseMove, AddressOf Item_MouseMove
AddHandler item.Control.MouseLeave, AddressOf Item_MouseLeave
List.Add(item)
RaiseEvent MouseEnter(item, System.EventArgs.Empty)
End Sub
Private Sub Item_MouseEnter(sender As Object, e As System.EventArgs)
Dim myItem As MessageDefinition
Dim mySender As Control = sender
For i As Integer = 1 To List.Count
myItem = List.Item(i - 1)
If myItem.Control Is mySender Then
RaiseEvent MouseEnter(myItem, e)
Exit Sub
End If
Next
End Sub
Private Sub Item_MouseMove(sender As Object, e As System.EventArgs)
Dim myItem As MessageDefinition
Dim mySender As Control = sender
For i As Integer = 1 To List.Count
myItem = List.Item(i - 1)
If myItem.Control Is mySender Then
RaiseEvent MouseMove(myItem, e)
Exit Sub
End If
Next
End Sub
Private Sub Item_MouseLeave(sender As Object, e As System.EventArgs)
Dim myItem As MessageDefinition
Dim mySender As Control = sender
For i As Integer = 1 To List.Count
myItem = List.Item(i - 1)
If myItem.Control Is mySender Then
RaiseEvent MouseLeave(myItem, e)
Exit Sub
End If
Next
End Sub
Public Event MouseEnter(sender As Object, e As System.EventArgs)
Public Event MouseMove(sender As Object, e As System.EventArgs)
Public Event MouseLeave(sender As Object, e As System.EventArgs)
End Class
As described (on Top) the catched Events are fired with "Standard"-Controls but not with the "Customized" Control.
If I change it and build up my own Events (with different names), which are not shadowing the Events from the derived control, it is also working as expected.
You don't override events in .NET - you can only override inherited event handlers, if any.
The event pattern in .NET is to create a public event in the base class and a protected virtual (VB Protected Overridable) method that raises that event and that can be overridden by a derived class. This method should be named OnEventName.
The Windows Forms controls follow this pattern, so to e.g. override when the Click event happens, you override the OnClick method:
Public Class MyTextBox
Inherits TextBox
Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
If SomeCondition() Then
MyBase.OnClick(e)
Else
Return 'Do not click
End If
End Sub
End Class
Obviously you can fiddle with the e argument as well.

Random delay in seconds from numericupdown in VB.Net

I have a desktop winforms app code:
Sub Delay(ByVal dblSecs As Double)
Const OneSec As Double = 1.0# / (1440.0# * 60.0#)
Dim dblWaitTil As Date
Now.AddSeconds(OneSec)
dblWaitTil = Now.AddSeconds(OneSec).AddSeconds(dblSecs)
Do Until Now > dblWaitTil
Application.DoEvents()
Loop
End Sub
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
Webbrowser1.Navigate(TextBox1.Text)
Delay(Val(DelayText.Text))
end sub
What I need is to set max. delay, same from textbox by entering seconds.
I need this to be random delay number so Im stacking here, thanks for correcting my code.
Also If its possible to make it in NumericUpDown, as i found some topics which says textbox text property is different as NumericUpDown but i like it more.
You could use an inbetween class which does most of the work for you
This class would take the WebBrowser, attach to some events of it, and would refresh periodically (depending on MinimumWait / MaximumWait)
As it is using threading, it also checks if the usercontrol needs to be invoked to Refresh it and when yes, invokes the custom refresh delegate
Public Class Refresher
Protected Delegate Sub RefreshNavigationDelegate(browser As WebBrowser)
Protected Sub RefreshNavigation(browser As WebBrowser)
If browser.InvokeRequired Then
browser.Invoke(New RefreshNavigationDelegate(AddressOf RefreshNavigation), browser)
Return
End If
browser.Refresh(WebBrowserRefreshOption.Completely)
End Sub
Private _isBusy As Boolean = False
Public Property IsBusy As Boolean
Get
Return _isBusy
End Get
Protected Set(value As Boolean)
If _isBusy = value Then
Return
End If
_isBusy = value
End Set
End Property
Public Property MinimumWait As Integer = 2000
Public Property MaximumWait As Integer = 10000
Private refreshThread As Thread = Nothing
Private _browser As WebBrowser
Public Property Browser As WebBrowser
Get
Return _browser
End Get
Set(value As WebBrowser)
If Object.Equals(_browser, value) Then
Return
End If
StopRefresh()
If _browser IsNot Nothing Then
RemoveHandler Browser.DocumentCompleted, AddressOf DocumentComplete
RemoveHandler Browser.Navigating, AddressOf Navigating
End If
_browser = value
If _browser IsNot Nothing Then
AddHandler Browser.DocumentCompleted, AddressOf DocumentComplete
AddHandler Browser.Navigating, AddressOf Navigating
AddHandler Browser.ProgressChanged, AddressOf ProgressChanged
End If
StartRefresh()
End Set
End Property
Protected Sub ProgressChanged(sender As Object, e As WebBrowserProgressChangedEventArgs)
IsBusy = e.CurrentProgress > 0 AndAlso e.CurrentProgress < e.MaximumProgress
End Sub
Protected Sub DocumentComplete(sender As Object, e As WebBrowserDocumentCompletedEventArgs)
IsBusy = False
End Sub
Protected Sub Navigating(sender As Object, e As WebBrowserNavigatingEventArgs)
IsBusy = True
End Sub
Public Sub StartRefresh()
If refreshThread IsNot Nothing Then
Return
End If
refreshThread = New Thread(AddressOf DoRandomRefreshes)
refreshThread.Start()
End Sub
Public Sub StopRefresh()
If refreshThread Is Nothing Then
Return
End If
refreshThread.Abort()
refreshThread = Nothing
End Sub
Protected Overridable Sub DoRandomRefreshes()
Dim randomGenerator As New Random()
While Not refreshThread.ThreadState = ThreadState.AbortRequested
Dim newTimeout As Integer = MinimumWait + randomGenerator.Next(MaximumWait - MinimumWait)
Thread.Sleep(newTimeout)
If Not IsBusy Then
RefreshNavigation(Browser)
End If
End While
End Sub
Public Sub New()
End Sub
End Class
You could then use it in your form as such:
Public Class Form1
Dim myRefresher As Refresher = New Refresher()
Private Sub tsbGo_Click(sender As Object, e As EventArgs) Handles tsbGo.Click
WebBrowser1.Navigate(txtUrl.Text)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
myRefresher.Browser = WebBrowser1
End Sub
Private Sub txtMin_TextChanged(sender As Object, e As EventArgs) Handles txtMin.TextChanged
Dim int As Integer = 0
If Integer.TryParse(txtMin.Text, int) Then
myRefresher.MinimumWait = int
End If
End Sub
Private Sub txtMax_TextChanged(sender As Object, e As EventArgs) Handles txtMax.TextChanged
Dim int As Integer = 0
If Integer.TryParse(txtMax.Text, int) Then
myRefresher.MaximumWait = int
End If
End Sub
End Class