vb.net form load and render speed too slow - vb.net

I have a mdi parent form which, when clicking a specific button on the screen, opens a new child form. When this form loads, it needs to call the database to retrieve information, the problem is that the form takes a lot of time to load, like 15 seconds, there's not too much code in the load sub, also, I tried to remove the database code from the load event, and, although it did make it a little faster, it still takes some time to load, is there a way to fix this?
This is my form
This is my code
Public Class Deposito
Dim FormPadre As MDICajero = New MDICajero
Private monedas As ArrayList = New ArrayList
Private Sub Deposito_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.WindowState = FormWindowState.Maximized
FormPadre = Me.MdiParent
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim ProximoForm As MenuPrincipal = New MenuPrincipal
FormPadre.LimpiarForm()
ProximoForm.MdiParent = FormPadre
ProximoForm.WindowState = FormWindowState.Maximized
ProximoForm.Show()
ProximoForm.CargaMenu(1)
End Sub
Private Sub BDepositar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BDepositar.Click
Dim dato As Emovimientos = New Emovimientos
dato.monto = montodeposito.Text
dato.idcuenta = nrocuenta.Text
dato.fecha = fechacobro.Value
End Sub End class
I've worked with java before and never seen so much load time between forms, even when retrieving information off a database.
EDIT: added a few lines to the constructor to make the form load faster, however, the rendering process it's still buggy.
Sub New()
Me.SetStyle(ControlStyles.DoubleBuffer Or ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.UserPaint, True)
InitializeComponent()
End Sub
EDIT 2: on the MDI parent form i used the same code that is automatically written when adding a mdi form to your solution, the only thing i added was an event for when the buttons are pressed to open the child forms:
Private Sub BRetiro_Click(sender As System.Object, e As System.EventArgs) Handles BRetiro.Click
Dim ProximoForm As Retiro = New Retiro
Me.LimpiarForm()
ProximoForm.MdiParent = Me
ProximoForm.WindowState = FormWindowState.Maximized
ProximoForm.Show()
End Sub
This is the code of the "LimpiarForm" function:
Public Sub LimpiarForm()
'borro todos los form hijos para no ocupar memoria, debe ser lo primero que tengo que hacer
Dim num As Integer
For num = 0 To Me.MdiChildren.Count - 1
Dim a = Me.MdiChildren(num)
a.Dispose()
Next
End Sub

Related

VB fires changetext event before control is loaded

I need to add some controls to a Visual Basic 2017 form programmatically. One of the controls is a textbox that needs a changetext event handler. Below is some code that accomplishes that task.
HOWEVER, the changetext event handler seems to fire right away, before the form even loads... before the textbox itself even loads! A "click" handler works fine, as expected. But changetext? Nope.
I've thrown together a simplified version to demonstrate. The line with the "DIES RIGHT HERE" comment causes the problem (not the comment, but the code to the left of it).
A textbox that is added at design time will work fine, not cause this problem, but that isn't an option.
What's causing this the changetext handler to be run early? How do I work around this?
Public Class Form1
Dim txtTest As TextBox
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim pntTextBox As Point
pntTextBox.X = 100
pntTextBox.Y = 100
txtTest = New TextBox
With txtTest
.Location = pntTextBox
.Width = 100
AddHandler txtTest.TextChanged, AddressOf txtTest_TextChanged
End With
Me.Controls.Add(txtTest)
End Sub
Private Sub txtTest_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyClass.TextChanged
Dim strTest As String
strTest = Str(txtTest.Width) ' ****** DIES RIGHT HERE
MsgBox(strTest)
End Sub
End Class
Made a few changes. Works.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For x As Integer = 1 To 2 'create multiple TB's
Dim pntTextBox As Point
pntTextBox.X = 100 * x
pntTextBox.Y = 100
Dim txtTest As TextBox = New TextBox
With txtTest
txtTest.Name = "tb_" & x.ToString
AddHandler txtTest.TextChanged, AddressOf txtTest_TextChanged
.Location = pntTextBox
.Width = 100
End With
Me.Controls.Add(txtTest)
Next
End Sub
Private Sub txtTest_TextChanged(ByVal sender As Object,
ByVal e As System.EventArgs) 'no handler at design time
Dim tb As TextBox = DirectCast(sender, TextBox)
Dim strTest As String
strTest = tb.TextLength.ToString
Debug.WriteLine("{0} {1}", tb.Name, strTest) 'put breakpoint here
End Sub
End Class

How continually output text to a RichTextBox with it being visually noticeable?

I am just trying to make my own VB project right now to get familiar with the language, and all I would like for it to do is continually print a string to the next line in a RichTextBox.
The issue that I can't figure out is to have it print one after another, it is printing all at once. Ill have some code down below to show where I am at right now.
I've tried using different counting methods, and depending on how it is set up, the debugger won't even load...
Friend WithEvents TableLayoutPanel1 As System.Windows.Forms.TableLayoutPanel
Friend WithEvents Button1 As System.Windows.Forms.Button
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
End Sub
Private Sub RTB1_TextChanged(sender As System.Object, e As System.EventArgs)
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim counter1 As Integer = 0
Dim i As String = "- I" & vbCrLf
While counter1 <= 10
Timer1.Interval = 1000
Timer1.Start()
i = i + i
counter1 += 1
End While
RichTextBox1.Text = i
'Loop
'Environment.NewLine
End Sub
Friend WithEvents TableLayoutPanel2 As System.Windows.Forms.TableLayoutPanel
Private Sub TableLayoutPanel2_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles TableLayoutPanel2.Paint
End Sub
Friend WithEvents RichTextBox1 As System.Windows.Forms.RichTextBox
Private Sub RichTextBox1_TextChanged(sender As System.Object, e As System.EventArgs) Handles RichTextBox1.TextChanged
RichTextBox1.SelectionStart = RichTextBox1.Text.Length
RichTextBox1.ScrollToCaret()
End Sub
Friend WithEvents Timer1 As System.Windows.Forms.Timer
Thank you to anyone that takes the time to look at this and help me out!
I really am looking for my output to scroll down the RichTextBox and continually to output a string on a new line over and over again one at a time.
As described:
Create a System.Windows.Forms.Timer. There are different types of Timers available. This is the one you need to update an UI component, since it's Tick event is raised in the UI thread.
Initialize the Timer and set its Interval to 1 second (1000 ms). The initialization is performed in the Shown() event of the Form, which is raised when the Form is ready to be presented (see the Docs).
Add the Timer.Tick event handler (here is added in code)
Initialize an Integer field (here, called timerCounter) which is incremented each time the Timer Ticks.
In the Tick event, add a line of text to the RichTextBox control using it's AppendText() method, which allows to add text to the control without clearing it. This method is common to all controls that inherit TextBoxBase.
Note:
I'm adding the text to the RichTextBox using an interpolated string $"{Some value}". If your version of VB.Net doesn't suppport it, use the older format:
RichTextBox1.AppendText("Line number " & timerCounter.ToString() & Environment.NewLine)
Private rtbTimer As System.Windows.Forms.Timer
Private timerCounter As Integer = 0
Protected Sub TimerTick(sender As Object, e As EventArgs)
timerCounter += 1
RichTextBox1.AppendText($"Line number {timerCounter} {Environment.NewLine}")
RichTextBox1.ScrollToCaret()
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
rtbTimer = New Windows.Forms.Timer With { .Interval = 1000 }
AddHandler rtbTimer.Tick, AddressOf TimerTick
rtbTimer.Start()
End Sub

Custom Textbox Zoom - Return text to active datagridview cell?

I have 2 Datagridview controls in same form. Each Datagrid has some columns where user will write long texts, so I designed form with RichTextBox that opens when user double-clicks these columns to enlarge text-entry. Code works, but I want to use same form for both Datagrids, so I should somehow return text to active datagridview cell. Here is my code (for Datagridview1):
TextZoomForm:
Public Class TextZoomForm
Public OpenedForm1 As New Form1
Private Sub RichTextBox1_DoubleClick(sender As Object, e As EventArgs) Handles RichTextBox1.DoubleClick
OpenedForm1.DataGridView1.CurrentCell.Value = RichTextBox1.Text
OpenedForm1.Label24.Focus()
Me.Close()
End Sub
Private Sub TextZoom_Load(sender As Object, e As EventArgs) Handles Me.Load
RichTextBox1.Text = OpenedForm1.DataGridView1.CurrentCell.Value
End Sub
End Class
DataGridView1_CellMouseDoubleClick in Form1:
Private Sub DataGridView1_CellMouseDoubleClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.CellMouseDoubleClick
If e.ColumnIndex = 1 Then
Dim cp = Cursor.Position
cp.Y += CInt(Cursor.Size.Height * (-0.5))
cp.X += CInt(Cursor.Size.Width * 0.8)
Dim f As New TextZoomForm()
f.OpenedForm1 = Me
f.Show()
f.Location = New Point(cp)
End If
End Sub
Any ideas on how to return text to active datagridview cell?
Change your zoomed form so that it doesn't know where its data comes from. Instead the control using it will pass the data.
Public Class TextZoomForm
Public Property ZoomedText As String
Get
Return RichTextBox1.Text
End Get
Set(value As String)
RichTextBox1.Text = value
End Set
End Property
Private Sub RichTextBox1_DoubleClick(sender As Object, e As EventArgs) Handles RichTextBox1.DoubleClick
Me.Close()
End Sub
End Class
To call the form change your code to the following:
Private Sub DataGridView1_CellMouseDoubleClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.CellMouseDoubleClick
...
Dim f As New TextZoomForm()
f.ZoomedText = DataGridView1.CurrentCell.Value
f.ShowDialog()
'Great breakpoint location.
DataGridView1.CurrentCell.Value = f.ZoomedText
Label24.Focus()
....
End Sub
Using ShowDialog prevents the user from changing the current cell part way through your call.
If you need it modeless then you should:
store the cell that the user has selected
handle the FormClosing event.
Test the DialogResult to make sure the user pressed ok
write the data back to the stored cell.

How to use threading for Loading Bar WinForm?

I am wanting to have a an infinite loop progress bar, just to give the user something to stare at during long load times. Currently the user will select a SQL query to execute, and results get displayed onto another winform that contains a gridview for the query results. My goal is to have another winform(loading form) that just has a progress bar on it that just infinitely fills to end and resets over and over until the gridview on the results form finishes rendering. I tried a background worker because i believe this will need multi threading for performance but the load form never shows up. Basically the execution plan should be this:
User clicks execute button, show progress bar on load form(infinite loop), Executes query and loads result form
Closes progress bar on load form
The above execution is called from my Main form
Private Sub LoadingForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
pbSqlCall.Minimum = 0
pbSqlCall.Maximum = 100
pbSqlCall.Step = 10
Dim Counter As Integer = 0
While Counter < 100
pbSqlCall.Increment(10)
Counter += 10
If Counter = 100 Then
Counter = 0
pbSqlCall.Value = 0
End If
End While
End Sub
BackgroundWorker1.RunWorkerAsync()
ExecuteQuery(Parameters, Queries.Item(ddlQueries.SelectedIndex))
'Not sure how to close the form using the thread
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
lf.ShowDialog() 'Load form
End Sub
You can do the following given a form called 'Loader' and a form called 'Main'
Loader:
Public Class Loader
Private Sub Loader_Load(sender As Object, e As EventArgs) Handles MyBase.Load
pbSqlCall.Style = ProgressBarStyle.Marquee
pbSqlCall.MarqueeAnimationSpeed = 30
End Sub
End Class
Main:
Imports System.Threading.Tasks
Public Class Main
Private Sub DoWork_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lf As New Loader
lf.Show(Me)
Task.Factory.StartNew(Sub()
'go get the data for the grid
System.Threading.Thread.Sleep(6000)
End Sub) _
.ContinueWith(Sub(result As task)
'check the aggregate exception
Dim aex As System.AggregateException = result.Exception
If aex IsNot Nothing Then
MessageBox.Show(String.Format("something bad happened: ", aex.Flatten.Message))
End If
'bind the data to the grid
lf.Close()
lf.Dispose()
End Sub, TaskScheduler.FromCurrentSynchronizationContext)
End Sub
Private Sub Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
End Class

Winforms ListBox Control Not Updating After Source Changes

I have a ListBox (LB) with a DataTable (DT) DataSource in the Form Class globally populated in the Form_Load event.
Private Sub frmEditPresets_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
DT.Columns.Add("DisplayText")
DT.Columns.Add("PresetID")
For Each TSI As ToolStripItem In Presets.DropDownItems
If TSI.Name.IndexOf("preset_") > -1 Then
DT.Rows.Add(TSI.Text, TSI.Name)
End If
Next
LB.DataSource = DT
LB.DisplayMember = "DisplayText"
End Sub
When I use my Rename button. It updates the menu item and the Data Source but the Listbox doesn't refresh until I click another item in the listbox.
Rename code:
Private Sub btnRename_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRename.Click
Dim R As DataRowView = LB.SelectedItem
Dim S As String = InputBox("Preset Name", "Rename", R("DisplayText"))
If S.Trim.Length = 0 Then Exit Sub
If Presets.DropDownItems.ContainsKey(R("PresetID").ToString) Then
Presets.DropDownItems(R("PresetID").ToString).Text = S
End If
R("DisplayText") = S
End Sub
I'm sure this is a simple question with a simple answer but I can't seem to figure it out. I've tried Refresh(). I've tried setting the DataSource again. I read this StackOverflow question Winforms listbox not updating when bound data changes but ResetBindings() doesn't seem to be an available method in this context.
*Edit. I gave Steve credit for the answer as he mentioned BindingContext. Although, that led me to find BindingContext(DT).EndCurrentEdit() which updated my LB display and maintained the selection.
Tried with this, and it works.....
Private Sub btnRename_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRename.Click
Dim R As DataRowView = LB.SelectedItem
Dim S As String = InputBox("Preset Name", "Rename", R("DisplayText"))
If S.Trim.Length = 0 Then Exit Sub
If Presets.DropDownItems.ContainsKey(R("PresetID").ToString) Then
Presets.DropDownItems(R("PresetID").ToString).Text = S
End If
R("DisplayText") = S
BindingContext(DT).EndCurrentEdit()
End Sub