I am doing some transition coding, using the .net transitions library found # http://code.google.com/p/dot-net-transitions/. I am trying to add an event to fire on transitions completed. In my sub, I have the following statements:
Private Sub btnLogin_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLogin.Click
If md5Password = rtnPassHash Then
AddHandler Me.TransitionCompletedEvent, AddressOf theHandlerFunction
Dim tr_empID = New Transition(New TransitionType_Linear(500))
tr_empid.add(txtEmployeeID, "BackColor", Color.LightGreen)
Dim tr_passw = New Transition(New TransitionType_Linear(500))
tr_passw.add(txtPassword, "BackColor", Color.LightGreen)
tr_empID.run()
tr_passw.run()
AddHandler Me.TransitionCompletedEvent, AddressOf theHandlerFunction
Dim tr_empID = New Transition(New TransitionType_Linear(500))
tr_empid.add(txtEmployeeID, "BackColor", Color.LightGreen)
Dim tr_passw = New Transition(New TransitionType_Linear(500))
tr_passw.add(txtPassword, "BackColor", Color.LightGreen)
tr_empID.run()
tr_passw.run()
end if
end sub
Outside of that sub I have:
Public Event TransitionCompletedEvent As EventHandler(Of Transition.Args)
Private Sub theHandlerFunction(ByVal sender As Object, ByVal args As Transition.Args) Handles Me.TransitionCompletedEvent
MsgBox("Event Fired")
End Sub
However, the event is not firing after the transition has finished. Why would this be?
Basic design:
Public Class Transition
Public Event TransitionCompleted(args As Transition.Args)
Public Sub SomeSub()
RaiseEvent TransitionCompleted(New Transition.Args With {set some properties})
End Sub
...
End Class
Public Class Form1
Private transition1 As New Transition
Private Sub Login_Click(...) ...
...
Addhandler transition1.TransitionCompleted, AddressOf TransitionCompleted
End Sub
Private Sub TransitionCompleted(args As Transition.Args) ' no handles clause
MessageBox.Show("event fired")
End Sub
End Class
Related
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.
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
I have a form that loads just fine, and I'm trying to fire off a task using a Background Worker as it loads.
I'm getting no errors with the code below, but the bw.DoWork event doesn't seem to be firing.
Am I missing something here? Thanks.
Here is my form Class -
Public Class mainForm
Dim objWorker As MyWorker
Private Sub mainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Call Me.loadForm()
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
Call Me.closeForm()
End Sub
Private Sub loadForm()
Me.objWorker = New MyWorker ' Invoke the background worker
End Sub
Private Sub closeForm()
Me.objWorker.bw_Cancel() ' Cancel the background worker
Me.Close() ' Close the form
End Sub
End Class
Here is my BackgroundWorker Class -
Imports System.ComponentModel
Partial Public Class MyWorker
Private bw As BackgroundWorker = New BackgroundWorker
Public Sub New()
bw.WorkerReportsProgress = False
bw.WorkerSupportsCancellation = True
AddHandler bw.DoWork, AddressOf bw_DoWork
AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
For i = 1 To 10
If bw.CancellationPending = True Then
e.Cancel = True
Exit For
Else
System.Threading.Thread.Sleep(500)
MsgBox("iteration " & i)
End If
Next
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
MsgBox("Complete!")
End Sub
Public Sub bw_Cancel()
If bw.WorkerSupportsCancellation = True Then
bw.CancelAsync()
End If
End Sub
End Class
add to MyWorker constructor ('new' method) this line:
bw.RunWorkerAsync()
I am stuck updating a progressbar from a different thread.
I did get it running in the simplest way, but then cleaning the code gets me stuck.
My testing code looks like all the examples on the web related to backgroundworker and BeginInvoke.
FormP is the Progressbar-Form.
This works:
Public Class Form1
Private Delegate Sub delegate_ProgressUpdate(ByVal paramValue As Integer,
ByVal paramMax As Integer)
Private Sub Button1_Click(sender As System.Object,
e As System.EventArgs) Handles Button1.Click
' Test 01:
' Show Progressbar via BGW
' All functions are within Form1
Dim bgw As New BackgroundWorker()
AddHandler bgw.DoWork, AddressOf BGW_Sample01_DoWork
FormP.Show(Me)
bgw.RunWorkerAsync()
End Sub
Private Sub invokeMe_ProgressUpdate(ByVal paramValue As Integer, ByVal paramMax As Integer)
FormP.ProgressBar1.Maximum = paramMax
FormP.ProgressBar1.Value = paramValue
FormP.ProgressBar1.Update()
End Sub
Private Sub BGW_Sample01_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
For i As Integer = 1 To 10
Threading.Thread.Sleep(500) ' Test delay
Me.BeginInvoke(New delegate_ProgressUpdate(AddressOf invokeMe_ProgressUpdate),
i, 10)
Next
MessageBox.Show("Fertig")
End Sub
If I try to make things work more orderly encapsulated in FormP, it doesn't work.
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim bgw As New BackgroundWorker
AddHandler bgw.DoWork, AddressOf BGW_Sample02_DoWork
FormP.Show(Me)
bgw.RunWorkerAsync()
End Sub
Private Sub BGW_Sample02_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
For i As Integer = 1 To 10
Threading.Thread.Sleep(500)
FormP.SetProgress(i, 10)
Next
MessageBox.Show("Fertig")
End Sub
' ########## FormP #################
Public Class FormP
Private Delegate Sub delegate_ProgressUpdate(ByVal value As Integer, ByVal maximum As Integer)
Public Sub SetProgress(ByVal paramValue As Integer, ByVal paramMaximum As Integer)
If Me.InvokeRequired Then
Me.Invoke(New delegate_ProgressUpdate(AddressOf Me.SetProgress), paramValue, paramMaximum)
Else
Me.ProgressBar1.Maximum = paramMaximum
Me.ProgressBar1.Value = paramValue
Me.ProgressBar1.Update()
End If
End Sub
End Class
FormP does not freeze, but UI is not updated.
Actually Me.InvokeRequired is false and I think that's where I begin to miss some important parts.
I tried Form1.InvokeRequired here, but it's false as well.
My understanding is: the calling thread here is the bgw thread, no matter in what class the code is that this thread calls...
That seems not to be it?
Thanks for any thoughts.
What worked eventually:
Private frmP As FormP
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim bgw As New BackgroundWorker
If Me.frmP IsNot Nothing AndAlso Me.frmP.Visible Then Return
Me.frmP = New FormP
Me.frmP.Show(Me)
AddHandler bgw.DoWork, AddressOf BGW_Sample02_DoWork
bgw.RunWorkerAsync(New Object() {Me.frmP})
End Sub
Private Sub BGW_Sample02_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
Dim objFrmP As FormP = DirectCast(e.Argument(0), FormP)
For i As Integer = 1 To 10
objFrmP.setProgress(i, 10)
Threading.Thread.Sleep(500)
Next
MessageBox.Show("Finished")
End Sub
The Progress-Dialog-Code in FormP:
Public Sub setProgress(paramValue As Integer, paramMaximum As Integer)
If Me.InvokeRequired Then
' defining a delegate type is not really necessary
Me.Invoke(Sub() Me.setProgress(paramValue, paramMaximum))
Else
Me.ProgressBar1.Maximum = paramMaximum
Me.ProgressBar1.Value = paramValue
Me.ProgressBar1.Update()
End If
End Sub
The event handlers in my parent class are never called though the events are raised in the child class.
The Code:
Public Class childForm
Public Event checkboxchangedEvent(ByVal checkbox1 As Boolean, ByVal checkbox2 As Boolean)
Private Sub checkboxchanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged, CheckBox2.CheckedChanged
RaiseEvent checkboxchangedEvent(CheckBox1.Checked, CheckBox2.Checked)
End Sub
End Class
Public Class ParentForm
Friend WithEvents cf As childform = New childform
Private Sub cf_checkboxchanged(ByVal checkbox1 As Boolean, ByVal checkbox2 As Boolean) Handles cf.checkboxchangedEvent
My.Settings.checkbox1 = checkbox1
My.Settings.checkbox2 = checkbox2
End Sub
End Class
You could try it like this as an alternative method of setting up the event handler,
Public Sub ShowChildForm()
Dim frm as New childform
AddHandler frm.checkboxchangedevent, AddressOf cf_checkboxchanged
frm.ShowDialog()
RemoveHandler frm.checkboxchangedevent, AddressOf cf_checkboxchanged
End Sub
I think your issue is timing. Try explicitly creating the form and adding the handlers in ParentForm's Load event handler. (This is all typed from memory and untested so event names/signatures for the Load event may be incorrect.)
Public Class ParentForm
Friend WithEvents cf As childform
Private Sub cf_checkboxchanged(ByVal checkbox1 As Boolean, ByVal checkbox2 As Boolean)
My.Settings.checkbox1 = checkbox1
My.Settings.checkbox2 = checkbox2
End Sub
Private Sub ParentForm_Load(ByVal sender as object, ByVal e as EventArgs) Handles Me.Load
cf = new childForm()
AddHandler cf.checkboxchanged, AddressOf cf_checkboxchanged
cf.Show()
End Sub
End Class