I have a datagridView(dgv) in the active tab(tabControl) that is filled with data obtained from a web service, when i start the query i create a separated thread that will assign the data to the dgv on his RunWorkerCompleted event, but then the dgv doesn't select a row when i make a click on it, in order to work properly i have to select the other tab and select again the tab containing this dgv
-the dgv still responds to the event cellContentClick
some code:
Private Sub backgroundWorker1_DoWork(sender As System.Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
Try
If UCA1.getAlumnos(codCarrrera, anio, ciclo, carnet_opc).alumnosArray IsNot Nothing Then
For i As Integer = 0 To UCA1.getAlumnos(codCarrrera, anio, ciclo, carnet_opc).alumnosArray.Length - 1
Dim a As sv.edu.uca.wsprb.alumnos = UCA1.getAlumnos(codCarrrera, anio, ciclo, carnet_opc).alumnosArray(i)
'here i add the rows
'TablaFAlumno.Rows.Add(...)
If i < 10 Then
BackgroundWorker1.ReportProgress(10)
End If
Next
Else
TablaFAlumno.Rows.Clear()
End If
Catch ex As System.Net.WebException
MessageBox.Show("->" + ex.Message)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub backgroundWorker1_ProgressChanged(sender As System.Object, e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
If ProgressBar1.Value = 0 Then
ProgressBar1.Visible = True
End If
If ProgressBar1.Value < 100 Then
ProgressBar1.Value += 10
End If
End Sub
Private Sub backgroundWorker1_RunWorkerCompleted(sender As System.Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If e.Error IsNot Nothing Then
MessageBox.Show("E -->" + e.Error.Message)
ElseIf e.Cancelled = True Then
ProgressBar1.Visible = False
MessageBox.Show("C -->" + e.Error.Message)
End If
ProgressBar1.Visible = False
dgvAlumnos.DataSource = TablaFAlumno
End Sub
try ad the end :
ProgressBar1.Visible = False
'TabControl name with Ficha Alumno
Me.TabControl1.SelectedIndex = 0
dgvAlumnos.DataSource = TablaFAlumno
dvgAlumnos.Select()
End Sub
Related
As stated I have a BackgroundWorker that runs a sub function DoHeavyWork().
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
If BackgroundWorker1.CancellationPending = True Then
e.Cancel = True
Else
'DO HEAVY WORK
DoHeavyWork()
End If
End Sub
Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
ProgressBar1.Value = e.ProgressPercentage
Label8.Text = e.ProgressPercentage.ToString() + " %"
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If e.Cancelled = True Then
ProgressBar1.Value = 0
Label8.Text = ""
ElseIf e.Error IsNot Nothing Then
MessageBox.Show(e.Error.Message)
Else
MessageBox.Show("Completed!")
End If
End Sub
Inside this sub function DoHeavyWork(), there are codes to update another form's GUI.
Private Sub DoHeavyWork()
For i As Integer = 1 To fresult_counter
Dim fresult As New Button
fresult.Name = "fresult_" & i
fresult.Text = result(index_acc(i - 1)).ToString
fresult.TextAlign = ContentAlignment.MiddleLeft
fresult.Width = 265
fresult.AutoSize = True
fresult.BackColor = Color.White
With fresult.FlatAppearance
.BorderColor = Color.White
.BorderSize = 2
.MouseDownBackColor = Color.DeepSkyBlue
.MouseOverBackColor = Color.DeepSkyBlue
End With
fresult.Anchor = AnchorStyles.Left
fresult.FlatStyle = FlatStyle.Flat
fresult.UseVisualStyleBackColor = False
fresult.Location = New Point(0, 22 * (i - 1))
Form1.TabControl2.TabPages(1).Controls.Add(fresult)
BackgroundWorker1.ReportProgress(i)
Next
End Sub
The problem is it did not update the GUI but the progress bar is working. I've tried getting the set of code out of the BackgroundWorker and it works fine. Is there something I did not set to enable BackgroundWorker to update the GUI?
As mentioned by jmcilhinney, the solution for my answer is very simple.
Just let the BackgroundWorker update the progress bar at the background. And when it finished doing it's work, the progress bar will be at 100 which means it is completed.
Once it is completed, simply add the update GUI codings (in my case: 'Form1.TabControl2.TabPages(1).Controls.Add(fresult)') at the sub function when BackgroundWorker has completed:
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If e.Cancelled = True Then
ProgressBar1.Value = 0
Label8.Text = ""
ElseIf e.Error IsNot Nothing Then
MessageBox.Show(e.Error.Message)
Else
MessageBox.Show("Completed!")
Form1.TabControl2.TabPages(1).Controls.Add(fresult)
End If
End Sub
Attempted to read or write protected memory. This is often an
indication that other memory is corrupt.
This was the error after I set the Image to my PictureBox. Its working fine but later on the error just pop-out.
Here is my code.
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Try
Dim cap As New Capture() 'first line
PictureBox1.Image = cap.QueryFrame.ToBitmap 'this line AccessViolationException
Catch ex As Exception
Timer1.Stop()
MsgBox("CAMERA ERROR " & ex.Message)
End Try
End Sub
Private Sub MetroTile1_Click(sender As Object, e As EventArgs) Handles MetroTile1.Click
Try
Dim cap As New Capture() 'first line
Select Case MetroTile1.Text
Case "Capture"
Timer1.Start()
MetroTile1.Text = "OK"
Case "OK"
Timer1.Stop()
frmStudentAddEdit.picImage.Image = PictureBox1.Image
MetroTile1.Text = "Capture"
Me.Close()
End Select
Catch ex As Exception
Timer1.Stop()
End Try
End Sub
The cap.QueryFrame.ToBitmap is the AccessViolationException was unhandled error.
How can I Fix this ? What causing this error ? Please Help.
Aim for something like the following.
Capture is a member of the form (not created new each time)
oldImage is disposed of after replacing
Private mCapture As Capture
Private Sub Form12_Load(sender As Object, e As System.EventArgs) Handles Me.Load
mCapture = New Capture()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Try
Dim oldImage = PictureBox1.Image
Dim newFrame = mCapture.QueryFrame.ToBitmap
PictureBox1.Image = newFrame.ToBitmap
If oldImage IsNot Nothing Then oldImage.Dispose()
Catch ex As Exception
Timer1.Stop()
MsgBox("CAMERA ERROR " & ex.Message)
End Try
End Sub
Private Sub MetroTile1_Click(sender As Object, e As EventArgs) Handles MetroTile1.Click
Try
Select Case MetroTile1.Text
Case "Capture"
Timer1.Start()
MetroTile1.Text = "OK"
Case "OK"
Timer1.Stop()
frmStudentAddEdit.picImage.Image = PictureBox1.Image
MetroTile1.Text = "Capture"
Me.Close()
End Select
Catch ex As Exception
Timer1.Stop()
End Try
End Sub
Application Screenshot:
Application Code:
Dim myController As New System.ServiceProcess.ServiceController("SQL Server (SQLEXPRESS)")
Sub ed()
If txtNum.Text = "Started" Then
btnStart.Enabled = False
btnStop.Enabled = True
ElseIf txtNum.Text = "Stopped" Then
btnStop.Enabled = False
btnStart.Enabled = True
End If
End Sub
Sub Na1()
If myController.Status = ServiceProcess.ServiceControllerStatus.Running Then
txtNum.Text = "Started"
ElseIf myController.Status = ServiceProcess.ServiceControllerStatus.Stopped Then
txtNum.Text = "Stopped"
End If
End Sub
Private Sub Test_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Na1()
ed()
End Sub
Private Sub Test_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
Me.Refresh() '////////This one is not required
End Sub
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
ProgressBar1.Value = 0
Try
myController.Start()
Catch ex As Exception
MsgBox(ex.Message)
Finally
ProgressBar1.Value = 100
Na1()'//////////////////////////////////////////////Edit Code here
End Try
End Sub
Private Sub txtNum_TextChanged(sender As Object, e As EventArgs) Handles txtNum.TextChanged
ed()
End Sub
Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click
ProgressBar1.Value = 0
Try
myController.Stop()
Catch ex As Exception
MsgBox(ex.Message)
Finally
ProgressBar1.Value = 100
Na1() '//////////////////////////////////////////////Edit Code here
End Try
End Sub
You need to stop SQL Service to Copy .mdf File and it is very irritating by Stopping/Starting the service manually from 'Services' so I tried to make it easier by using Vb.Net coding...
Edit the Following codes,
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
ProgressBar1.Value = 0
Try
myController.Start()
Catch ex As Exception
MsgBox(ex.Message)
Finally
ProgressBar1.Value = 100
Na1()'//////////////////////////////////////////////Edit Code here
End Try
End Sub
To
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
ProgressBar1.Value = 0
Try
myController.Start()
Catch ex As Exception
MsgBox(ex.Message)
Finally
ProgressBar1.Value = 100
myController.WaitForStatus(ServiceProcess.ServiceControllerStatus.Running)'//Add
Na1()
End Try
End Sub
And
Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click
ProgressBar1.Value = 0
Try
myController.Stop()
Catch ex As Exception
MsgBox(ex.Message)
Finally
ProgressBar1.Value = 100
Na1() '//////////////////////////////////////////////Edit Code here
End Try
End Sub
To
Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click
ProgressBar1.Value = 0
Try
myController.Stop()
Catch ex As Exception
MsgBox(ex.Message)
Finally
ProgressBar1.Value = 100
myController.WaitForStatus(ServiceProcess.ServiceControllerStatus.Stopped) '//Add
Na1()
End Try
End Sub
And all is done!
I want to create a button that could stop my background worker and end all the process it is working on.
Here is my sample backgroundworker code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
If BackgroundWorker1.IsBusy <> True Then
BackgroundWorker1.RunWorkerAsync()
End If
Catch ex As Exception
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim counter As Integer = 1
Do
'updated code with stop function----------------
BackgroundWorker1.WorkerSupportsCancellation = True
If BackgroundWorker1.CancellationPending Then
e.Cancel = True
ProgressBar1.Value = 0
Exit Do
End If
'updated code with stop function----------------
ListBox1.Items.Add(counter)
ProgressBar1.Value = ((counter - 1) / limit) * 100
counter = counter + 1
Loop While(counter <= 999999999999999999)
End Sub
Private Sub BackgroundWorker1_ProgressChanged(sender As System.Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Try
Catch ex As Exception
End Try
End Sub
Private Sub BackgroundWorker1_Completed(sender As System.Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
Try
Catch ex As Exception
End Try
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False
End Sub
'updated code with stop function----------------
Private Sub StopButton_Click(sender As Object, e As EventArgs) Handles StopButton.Click
If BackgroundWorker1.IsBusy Then
If BackgroundWorker1.WorkerSupportsCancellation Then
BackgroundWorker1.CancelAsync()
End If
End If
End Sub
'updated code with stop function----------------
I want to reset the loop and return the Progress Bar to 0% when i stop the backgroundworker.
Is this possible?
The code above has been updated and it is now working fine.
I have added this code inside my do loop:
BackgroundWorker1.WorkerSupportsCancellation = True
If BackgroundWorker1.CancellationPending Then
e.Cancel = True
ProgressBar1.Value = 0
Exit Do
End If
I created a button that stops the worker:
Private Sub StopButton_Click(sender As Object, e As EventArgs) Handles StopButton.Click
If BackgroundWorker1.IsBusy Then
If BackgroundWorker1.WorkerSupportsCancellation Then
BackgroundWorker1.CancelAsync()
End If
End If
End Sub
The Backgroundworker class has the method CancelAsync() which you need to call to cancel the execution of the bgw.
You need to set the Backgroundworker.WorkerSupportsCancellation property to true and inside the while loop you need to check the CancellationPending property wether the value is true which indicates a call to the CancelAsync() method.
If CancellationPending evaluates to true, you would ( which you should have done already ) call one of the overloaded ReportProgress() (Docu) methods to set your ProgressBar value to the desired value.
EDIT: You should set the Cancel property of the DoWorkEventArgs to true so you can check the Cancelled property of the RunWorkerCompletedEventArgs inside the RunworkerCompletedevent.
You also shouldn not access any controls which lives in the UI thread. You better use the ProgressChanged(Docu) event.
See: BackgroundWorker Docu
Public Class Form1
Private iVal As Integer = 0
Private Sub bgw_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
For iVal = iVal To 100 Step 1
bgw.ReportProgress(iVal)
Threading.Thread.Sleep(99)
If (bgw.CancellationPending = True) Then
e.Cancel = True
Exit For
End If
Next
End Sub
Private Sub bgw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
pbar.Value = e.ProgressPercentage
lblProgrss.Text = e.ProgressPercentage.ToString() & "%"
End Sub
Private Sub bgw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
If (e.Cancelled = True) Then
pic.Visible = False
pbar.Value = iVal
lblProgrss.Text = iVal & "%"
btnstart.Text = "Start"
btnstart.BackColor = Color.Green
Else
pic.Visible = False
btnstart.Text = "Start"
btnstart.BackColor = Color.Green
iVal = 0
End If
End Sub
Private Sub btnstart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnstart.Click
If (btnstart.Text = "Start") Then
btnstart.Text = "Stop"
btnstart.BackColor = Color.Red
pic.Visible = True
bgw.RunWorkerAsync()
Else
If (bgw.IsBusy = True) Then
btnstart.Text = "Start"
btnstart.BackColor = Color.Green
bgw.CancelAsync()
End If
End If
End Sub
End Class
I have a form with over 10 textboxes and 1 button, I would like to disable the button with a realtime validation until all textboxes filled with a 10 or a 13 length numeric value, my code is the following so far:
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
For Each userID As Control In Me.Controls.OfType(Of TextBox)()
AddHandler userID.TextChanged, AddressOf ValidateAllFields
Next userID
End Sub
Private Sub userID_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs) Handles Me.KeyPress
If e.KeyChar <> ChrW(Keys.Back) Then
If Char.IsNumber(e.KeyChar) Then
Else
e.Handled = True
End If
End If
End Sub
Private Function ValidateAllFields()
Dim Validation As Boolean = True
For Each userID As Control In Me.Controls.OfType(Of TextBox)()
Dim e As New System.ComponentModel.CancelEventArgs
e.Cancel = False
Call userID_Validating(userID, e)
If e.Cancel = True Then Validation = False
Next userID
buttonSave.Enabled = Not Me.Controls.OfType(Of TextBox).Any(Function(userID) userID.Text.Length <> 10 AndAlso userID.Text.Length <> 13)
Return Validation
End Function
Private Sub userID_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles _
user00.Validating, _
user01.Validating, _
user02.Validating, _
user03.Validating, _
user04.Validating, _
user05.Validating, _
user06.Validating, _
user07.Validating, _
user07.Validating, _
user08.Validating, _
user09.Validating, _
user10.Validating, _
user11.Validating
If Not IsNumeric(sender.Text) OrElse (sender.Text.Length <> 10) AndAlso (sender.Text.Length <> 13) Then
ErrorProvider1.SetError(sender, "")
ErrorProvider2.SetError(sender, "Please enter a valid User ID.")
e.Cancel = True
Else
ErrorProvider1.SetError(sender, "Valid User ID.")
ErrorProvider2.SetError(sender, "")
End If
End Sub
Thanks to your help it works as I wanted, but can you help me improve/clean it? I'm still studying vb, I'm open to any suggestion. Thanks in advance!
Here you have a code performing the actions you want:
Dim done1, done2, done3 As Boolean
Dim targetLength1 As Integer = 10
Dim targetLength2 As Integer = 13
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Try
If (IsNumeric(TextBox1.Text)) Then
If (TextBox1.Text.Length = targetLength1 Or TextBox1.Text.Length = targetLength2) Then
done1 = True
End If
End If
If (done1 And done2 And done3) Then
Button1.Enabled = True
End If
Catch ex As Exception
End Try
End Sub
Private Sub TextBox2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged
Try
If (IsNumeric(TextBox2.Text)) Then
If (TextBox2.Text.Length = targetLength1 Or TextBox2.Text.Length = targetLength2) Then
done2 = True
End If
End If
If (done1 And done2 And done3) Then
Button1.Enabled = True
End If
Catch ex As Exception
End Try
End Sub
Private Sub TextBox3_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox3.TextChanged
Try
If (IsNumeric(TextBox3.Text)) Then
If (TextBox3.Text.Length = targetLength1 Or TextBox3.Text.Length = targetLength2) Then
done3 = True
End If
End If
If (done1 And done2 And done3) Then
Button1.Enabled = True
End If
Catch ex As Exception
End Try
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Button1.Enabled = False
End Sub
It accounts just for 3 textboxes (TextBox1, TextBox2 and TextBox3) and 1 button (Button1) but you can extend the idea to as many textboxes as you wish. It relies on the TextChanged even of each textbox. When the condition is met (given textbox has a number whose length is 10 or 13), the corresponding flag is set to true (e.g., done1 for TextBox1...). When all the flags are true (all the textboxes contain the expected information), the button is disabled.
I think would better to use TextChanged Event ..
Private Sub TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged, TextBox2.TextChanged, ....., TextBox10.TextChanged
Chk4ButtonEnabled()
End Sub
Sub Chk4ButtonEnabled()
Dim s as String
For Each userID As Control In Me.Controls
If userID.GetType Is GetType(TextBox) Then
s = userID.Text
If Not s.Length = 10 OR Not s.Length = 13 Then
ErrorProvider1.SetError(userID, "")
buttonSave.Enabled = False
Else
ErrorProvider1.SetError(userID, "Valid User ID.")
buttonSave.Enabled = True
End If
End If
Next
End Sub