cannot read from combo box to use as a variable in a sub-routine - vb.net

I am trying to have a variable input come from a combobox. i had thought it would be a simpler task but i am stuck on this and would be grateful for some help.
i am working with pre-packaged code that connects to an API, connects to a server and does stuff. I am customizing it to do a few additional calculations, all of which now work fine, but the variables i use to perform those calcs, inside of one of the sub-routines, are hard coded, and i want to be able to read them in instead using a combobox. i had done this many times using VB6 and VBA, but i am new to vb.net (2010) and even though i have the combobox on my form, every reference to the selected number in the combobox ends up with an empty result
in a simpler application, like the one below, i am able to get the data from the combo box:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim divisor As Integer
Dim res1 As Integer
If Int32.TryParse(ComboBox1.Text, divisor) Then
MsgBox(ComboBox1.Text)
Else
MsgBox("error" & ComboBox1.Text)
End If
res1 = divisor - 9
MsgBox(res1)
End Sub
End Class
Unfortunately the code i am working with is not cooperating with the code above. without posting all the code, here is the basic structure, maybe this will help you help me figure out where to write the code above so it will grab the value in the combobox where the 'divisor' in the sub13 (see below) will be the number from the combobox instead of it being hard coded
and every reference you see below to the combobox was 'auto-generated'. that is, once i placed the combobox on the form all of that code appeared.
Imports X.API
Public Class frmMain
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
InitializeComponent()
End Sub
Protected Sub Dispose(ByVal disposing As Boolean)
End Sub
Private components As System.ComponentModel.IContainer
Friend WithEvents Panel1 As System.Windows.Forms.Panel
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.ComboBox1 = New System.Windows.Forms.ComboBox()
Me.ComboBox1.FormattingEnabled = True
Me.ComboBox1.Location = New System.Drawing.Point(710, 117)
Me.ComboBox1.Name = "ComboBox1"
Me.ComboBox1.Size = New System.Drawing.Size(121, 21)
Me.ComboBox1.TabIndex = 3
End Sub
#End Region
#Region " Member Variables "
Private mTable As DataTable
#End Region
#Region " Form and Control Events "
Private Sub frmMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub frmMain_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
End Sub
Private Sub s1()
End Sub
Private Sub s2()
End Sub
Private Sub s3()
End Sub
Private Sub s4()
End Sub
#End Region
#Region " Operations "
Private Sub s5()
End Sub
Private Sub s6()
End Sub
Private Sub s7()
End Sub
Private Sub s8()
End Sub
#End Region
#Region " API Events "
Private Sub s8()
End Sub
Private Sub s9()
End Sub
Private Sub s10()
End Sub
Private Sub s11()
End Sub
Private Sub s12()
End Sub
#End Region
Private Sub s13()
Dim divisor As Integer = 1
'[this is where i want the divisor to draw from the combobox]
'so instead of "Dim divisor As Integer = 1"
i want "Dim divisor As Integer = contents of combobox
End Sub
' i have no idea why this code appears here
Friend WithEvents ComboBox1 As System.Windows.Forms.ComboBox
Private Class Item1
Public Sub s14()
End Sub
End Class
Private Class Item2
Public Sub s15()
End Sub
End Class
Private Class Item3
Public Sub s16()
End Sub
End Class
End Class
the sub i am working on is "s13()", but when i try to read from the combobox i get a blank.
exactly where to place the code that works as shown in my first example in the structure i show immediately above is unknown to me. i would have thought it would be much easier to read from a combobox, but i am stumped.

Given the names of your functions, it's difficult to tell exactly what you're trying to do. But you have a couple of options here. The function itself can access the value from the combo box if it's called while the combo box has a value in it, or the function can require the value as a function argument and whatever calls the function can pass the combo box's value.
For the first, it would look something like this:
Private Sub s13()
Dim divisor as Int32 = 1
If Int32.TryParse(Me.ComboBox1.Text, divisor) Then
' Perform your logic
Else
' The input wasn't a valid integer, maybe show an error?
End If
End Sub
Whereas the second approach might look like this:
Private Sub s13(ByVal divisor as Integer)
' Perform your logic
End Sub
And the code which calls that would need to get the value:
Dim divisor as Int32 = 1
If Int32.TryParse(Me.ComboBox1.Text, divisor) Then
s13(divisor)
Else
' The input wasn't a valid integer, maybe show an error?
End If
The main thing to note in all of this is that you should use Int32.TryParse() to determine if the inputted value in the combo box is actually an integer, and handle the error condition when it isn't.

You have to use the selected item :
If Int32.TryParse(ComboBox1.selectedItem, divisor) Then
MsgBox(ComboBox1.selectedItem)
Else
MsgBox("error" & ComboBox1.selectedItem)
End If

for anybody stuck with the same problem, here is the solution.
the code i had to work with is mammoth, so it would not let me pull in a combobox variable into any of the subs, esp as this is a multi-threaded prog. i knew, however, the solution had to be simple. and that is always something to keep in mind -- the solution is never that complicated, and you never need as much code as you think.
in this case i went down the path of a public variable,
Public Shared divisor As Integer
i placed this line underneath the very first line
Public Class frmMain
since there were other drop-down lists on the form that were clearly being drawn from, i went to the code associated with the button that initiated the steps to get the data from the server, just another button_click sub
if that sub pulled in the other combo boxes, then it had to grab the data in the one i wanted. all i did then was add this line of code to that button_click sub
divisor = ComboBox1.Text
since divisor is now a public variable, what was recorded in the button_click sub easily passes to another private sub that runs other routines. so anywhere in the code i want to use the variable 'divisor' all i have to do is mention it :)
if divisor > 0 then
'do something
end if

Related

BC30455 Argument not specified for parameter 'sender' of

i need help with my code
Public Class Forma
Private Sub ProjectToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ProjectToolStripMenuItem.Click
If ProjectToolStripMenuItem_Click() Then
Print(Form_load)
End If
End Sub
Private Sub Form_load(FormB As Object)
End Sub
End Class
but i keep getting BC30455 Argument not specified for parameter 'sender' of. What am i doing wrong
Your condition want to check the result of the event ProjectToolStripMenuItem_Click (click event of ProjectToolStripMenuItem). On this function you don't define the sender and e parameter.
You should review your code and fix the issues:
Public Class Forma
Private Sub ProjectToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ProjectToolStripMenuItem.Click
If exampleFunction() Then '<-- choose the correct function or variable
Print(Form_load) '<-- Form_load?? maybe FormB??
End If
End Sub
Private Sub Form_load(FormB As Object)
End Sub
End Class
Some basics you should know:
A Sub doesn't return a value, so you can't use a Sub on a condition (only functions, variables and values can be used on a condition).
It looks like you check if the button / menu item was clicked by the user. You don't need to check because the event ProjectToolStripMenuItem_Click is called automatically if the user click on ProjectToolStripMenuItem. At the point you try to check the button / menu item was clicked it was actually clicked. You can find more information about Event Handlers on the official .NET docs.
The error message should be clear enough to solve the issue:
You have not supplied an argument for a required parameter.
To correct this error:
Supply an argument for the specified parameter.
source: https://learn.microsoft.com/en-us/dotnet/visual-basic/misc/bc30455
You try to print the form on button click?
Public Class Forma
Private printForm as Object
Private Sub ProjectToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ProjectToolStripMenuItem.Click
If ConditionIsTrue() Then '<-- choose the correct Sub or Function
Me.printForm.Print()
End If
End Sub
Private Sub Form_load(FormB As Object)
'... maybe some other stuff
Me.printForm = FormB
'... maybe some other stuff
End Sub
End Class
You cannot pass a Sub as a Parameter Print(Form_load). FormB.Print() might be what you are looking for.
This looks like a problem : If ProjectToolStripMenuItem_Click() Then
It's a call to the same sub and it has no parameters specified.

Cannot set focus to textbox

I am using VB and trying to select a portion of the text in a textbox of a separate form. However, I can't seem to find a good way to access the textbox from the other form, although the textbox is public (I am new to VB).
Currently, I'm trying to do this by calling a function located in the form (the form with the textbox), and then focusing on the textbox and selecting/highlighting the text. But it still doesn't work:
Public Sub GetFindLoc(ByVal lngStart As Long, ByVal intLen As Integer)
frmFind.Hide()
MessageBox.Show(ActiveForm.Name)
MessageBox.Show(txtNotes.CanFocus())
txtNotes.Focus()
txtNotes.Select(lngStart, intLen)
frmFind.Show()
End Sub
With this, I first hide the original form, and then try to select the text, and bring back the form. It shows that the active form is the one which I'm trying to select the text on, but it returns false on CanFocus().
Any help would be appreciated, thank you!
Hmm. This was more fiddly than I thought. You need to pass a reference to the other form:
Main form:
Public Class frmNotes
'This is the main form
'This form has a textbox named txtNotes and a button called btnShowFind
'txtNotes has .MultiLine=True
Private mfrmFind As frmFind
Private Sub btnShowFind_Click(sender As Object, e As EventArgs) Handles btnShowFind.Click
If mfrmFind Is Nothing OrElse mfrmFind.IsDisposed Then
mfrmFind = New frmFind(Me)
mfrmFind.Show()
Else
mfrmFind.BringToFront()
End If
End Sub
End Class
Finder form:
Public Class frmFind
'This form has a textbox called txtFind and a button called btnFind
Private mfrmParent As frmNotes
Sub New(parent As frmNotes)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
mfrmParent = parent
End Sub
Private Sub btnFind_Click(sender As Object, e As EventArgs) Handles btnFind.Click
If txtFind.Text = "" Then
MsgBox("Please enter text to find", MsgBoxStyle.Exclamation)
Exit Sub
End If
Dim intSearchBegin As Integer = mfrmParent.txtNotes.SelectionStart + 1
Dim intStart As Integer = mfrmParent.txtNotes.Text.IndexOf(txtFind.Text, intSearchBegin)
If intStart > -1 Then
mfrmParent.txtNotes.Select(intStart, txtFind.Text.Length)
mfrmParent.txtNotes.Focus()
mfrmParent.BringToFront()
Else
mfrmParent.txtNotes.Select(0, 0)
MsgBox("No more matches")
End If
End Sub
End Class
Public Class frmFind
Private Sub btnFind_Click(sender As Object, e As EventArgs) Handles btnFind.Click
Dim search As String = TextBox1.Text.Trim
Dim pos As Integer = frmNotes.txtNotes.Text.IndexOf(search)
If pos > 0 Then
frmNotes.txtNotes.Focus()
frmNotes.txtNotes.Select(pos, search.Length)
End If
End Sub
End Class
This is just a "find" form with 1 textbox and 1 button which will highlight the first occurrence of the string in TextBox1 that it finds in txtNotes on the other form. If you want it to find whitespace as well, then remove the Trim function. You can add code to find other occurrences or go forward/backward.

How to call a Sub without knowing which form is loaded into panel?

On every DataGridView1_SelectionChanged event I need to run a Private Sub OnSelectionChanged() of the form that is loaded into Panel1 (see the image http://tinypic.com/r/2nu2wx/8).
Every form that can be loaded into Panel1 has the same Private Sub OnSelectionChanged() that initiates all the necessary calculations. For instance, I can load a form that calculates temperatures or I can load a form that calculates voltages. If different element is selected in the main form’s DataGridView1, either temperatures or voltages should be recalculated.
The problem is - there are many forms that can be loaded into Panel1, and I’m struggling to raise an event that would fire only once and would run the necessary Sub only in the loaded form.
Currently I’m using Shared Event:
'Main form (Form1).
Shared Event event_UpdateLoadedForm(ByVal frm_name As String)
'This is how I load forms into a panel (in this case frm_SCT).
Private Sub mnu_SCT_Click(sender As Object, e As EventArgs) Handles mnu_SCT.Click
frm_SCT.TopLevel = False
frm_SCT.Dock = DockStyle.Fill
Panel1.Controls.Add(frm_SCT)
frm_SCT.Show()
Var._loadedForm = frm_SCT.Name
RaiseEvent event_UpdateLoadedForm(Var._loadedForm)
End Sub
‘Form that is loaded into panel (Form2 or Form3 or Form4...).
Private WithEvents myEvent As New Form1
Private Sub OnEvent(ByVal frm_name As String) Handles myEvent.event_UpdateLoadedForm
‘Avoid executing code for the form that is not loaded.
If frm_name <> Me.Name Then Exit Sub
End Sub
This approach is working but I’m sure it can be done way better (I'd be thankful for any suggestions). I have tried to raise an event in the main form like this:
Public Event MyEvent As EventHandler
Protected Overridable Sub OnChange(e As EventArgs)
RaiseEvent MyEvent(Me, e)
End Sub
Private Sub DataGridView1_SelectionChanged(sender As Object, e As EventArgs) _
Handles DataGridView1.SelectionChanged
OnChange(EventArgs.Empty)
End Sub
but I don't know to subscribe to it in the loaded form.
Thank you.
Taking into account Hans Passant’s comments as well as code he posted in related thread I achieved what I wanted (see the code below).
Public Interface IOnEvent
Sub OnSelectionChange()
End Interface
Public Class Form1
' ???
Private myInterface As IOnEvent = Nothing
' Create and load form.
Private Sub DisplayForm(frm_Name As String)
' Exit if the form is already displayed.
If Panel1.Controls.Count > 0 AndAlso _
Panel1.Controls(0).GetType().Name = frm_Name Then Exit Sub
' Dispose previous form.
Do While Panel1.Controls.Count > 0
Panel1.Controls(0).Dispose()
Loop
' Create form by its full name.
Dim T As Type = Type.GetType("Namespace." & frm_Name)
Dim frm As Form = CType(Activator.CreateInstance(T), Form)
' Load form into the panel.
frm.TopLevel = False
frm.Visible = True
frm.Dock = DockStyle.Fill
Panel1.Controls.Add(frm)
' ???
myInterface = DirectCast(frm, IOnEvent)
End Sub
Private Sub DataGridView1_SelectionChanged(sender As Object, e As EventArgs) _
Handles DataGridView1.SelectionChanged
' Avoid error if the panel is empty.
If myInterface Is Nothing Then Return
' Run subroutine in the loaded form.
myInterface.OnSelectionChange()
End Sub
End Class
One last thing – it would be great if someone could take a quick look at the code (it works) and confirm that it is ok, especially the lines marked with “???” (I don’t understand them yet).

One button to control another button on many user controls

Hey and sorry for another strange question...
I have 25 UserControls with a Start_Button on each of them - this Start_Button can either be Visible or not depending on whether the UserControl is active. On my form1 I have a Start_All button.
I would like to simulate a click of all the UserControl's Start_Buttons which are visible only.
Instead of simulating click-events expose a method for the start-functionality and call this method from the Start_Button.Click-event. Then you can use this method from wherever you want. On this way your code remains readable and reusable.
You should also provide an Active property in your UserControl which you can simply link to your start-button's Visible-property.
Presuming that the user-controls are in a container-control like Panel:
Public Sub StartAll()
Dim allActiveUserControls =
From uc In controlPanel.Controls.OfType(Of MyUserControlType)()
Where uc.Active
For Each uc In allActiveUserControls
uc.Start()
Next
End Sub
Here is an example for the Active property:
Public Property Active As Boolean
Get
Return StartButton.Visible
End Get
Set(value As Boolean)
StartButton.Visible = value
End Set
End Property
and here are the Start method and the event-handlers:
Public Sub Start()
' Do Something ... '
End Sub
Private Sub StartButton_Click(sender As System.Object, e As System.EventArgs) Handles StartButton.Click
Start()
End Sub
Private Sub Start_All_Click(sender As System.Object, e As System.EventArgs) Handles Start_All.Click
StartAll()
End Sub

Initialize not properly make with classes vb.net

So, I need to do an program for a client and he wants a search bar in it. So I made it and everything worked perfectly but I put it in my main form. Now, I want to put it in a class but when I initialize the program, it gives me the following error
An error occurred while creating the form. For more information,
see Exception.InnerException. The error is: The form is self-reference during
construction from a default instance, which led to infinite recursion. In the
constructor of the form, refer to the form using 'Me'.
I tried to put Me.Rbtn_X... but it doesn't recognize it.
Initialization
' Main form
Public Sub New()
InitializeComponent()
Initialize_search()
End Sub
Initialize_search()
' Main form
' search is initialize like this :
' Dim search as New Research
Private Sub Initialize_search()
search.generate_autocomplete()
End Sub
generate_autocomplete()
' Research class
Sub generate_autocomplete()
' Main_form = Main form
Dim field = ""
' This is the place where the program fail
If Main_form.RbtnR_avancee_contact.Checked Then
field = "personneressource"
Else
field = "beneficiaire"
End if
' ....
End Sub
Is there something I didn't understand or It's not possible to do it that way?
Edit: added Form_shown event
Public Sub New()
InitializeComponent()
' Initialize_search()
End Sub
Private Sub Form_personne_Shown(sender As Object, e As EventArgs) Handles Me.Shown
MessageBox.Show("You are in the Form.Shown event.")
End Sub
The form is not created (fully) until New completes. By adding your Initialize_search to it, it eventually leads to the statement `Main_form.RbtnR_avancee_contact.Checked'. This is wrong on two counts:
1) the form doesnt exist yet, so you cant refer to it. (this is what the error meant with 'form is self-reference during construction')
2) the ref should be Me.RbtnR (which is what it meant by 'refer to the form using 'Me'')
Move your Initialize_search to the Form_shown event. Your code should look like this (including Lar's suggestion)
' Main form
Public Sub New()
' REQUIRED
InitializeComponent()
End Sub
If there is really something that needs to be setup for this, add it to the form_shown event:
Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.Shown
' NOTE: even .NET refers to ME not MainForm etc
InitializePanel
InitializeSeach
End Sub
Then:
Private Sub Initialize_search()
search.generate_autocomplete(Me.RbtnR_avancee_contact.Checked)
End Sub
Then:
Sub generate_autocomplete(AdvContact as Boolean)
Dim field AS STRING = ""
If AdvContact Then
field = "personneressource"
Else
field = "beneficiaire"
End if
' ....
End Sub
Your search class doesn't have a reference to the instance of the form's controls.
Try passing the value instead:
Sub generate_autocomplete(advancedChecked As Boolean)
Dim field As String = ""
If advancedChecked Then
field = "personneressource"
Else
field = "beneficiaire"
End if
End Sub
Then when you call it:
search.generate_autocomplete(Me.RbtnR_avancee_contact.Checked)
Even if did work like you want it to, according to your code, it would always result in field containing the same value (whichever was set in designer).
Instead, try putting this code inside RbtnR_avancee_contact.Checked event. Or even TextChanged for the autocomplete box (and initialize it for the first time user enters anything), it would examine the checked state and populate autocomplete items.
With this approach, if your user never uses the search box, you don't need to initialize it.