Combo Box Returning -1 For SelectedIndex - vb.net

I'm trying to pick up a combo box's selected index. This was working absolutely fine, then all of a sudden it started returning -1 no matter what item is selected
My code is:
Form Code
Private Sub Man_SelectedIndexChanged_1(sender As Object, e As EventArgs) Handles Man.SelectedIndexChanged, Units.SelectedIndexChanged
'Set Transducer Type
Call References.LevListAdd()
End Sub
References Module LevListAdd Sub
Public Sub LevListAdd()
Form1.Lev.Items.Clear()
If Form1.Man.Text = "Pulsar" Then
With Form1.Lev.Items
.Add("Ultra Range")
.Add("IMP Range")
.Add("Twin Range")
End With
End If
End Sub
This fills the combo box lev fine when the Man combo box item "Pulsar" is selected. I then want my users to click a button to generate some labels and stuff. The code is as such:
Button Click Code
Private Sub Generate_Click(sender As Object, e As EventArgs) Handles Generate.Click
If CheckGenerate() = False Then Exit Sub
Dim X = CheckGenerationType(Man.SelectedIndex, Lev.SelectedIndex, Level.Checked, Volume.Checked, ListBox1.SelectedIndex,
Units.SelectedIndex)
Call ParamPage(X)
End Sub
CheckGenerate simply checks that all boxes have been filled in. I pass the informtion from the form to the following function:
Public Function CheckGenerationType(Man As Integer, Lev As Integer, Level As Boolean, Volume As Boolean, TankType As Integer,
MeasurementUnit As Integer) As String
Dim M As Integer
Dim L As Integer
Dim CT As Integer
Dim TT As Integer
Dim Ms As Integer
M = Man
L = Lev
TT = TankType
Ms = MeasurementUnit
If Level = True Then
CT = 0
ElseIf Volume = True Then
CT = 1
End If
CheckGenerationType = CStr(M) + "." + CStr(L) + "." + CStr(CT) + "." + CStr(TT) + "." + CStr(Ms)
End Function
When the lev.selectedindex parameter arrives at this function, it reads -1. Even if the user has selected any of the 3 items. Can anyone explain why this is happening?

I've just tried your code. I get the same result (-1 in lev.SelectedIndex) and this was because jumped using tab through the controls my when i'm hitting the Man or Units Combobox it runs the LevListAdd() and then clears the Lev-ComboBox because of Form1.Lev.Items.Clear().
You should think about your call Man_SelectedIndexChanged_1 or maybe just use something like this:
Public Sub LevListAdd()
If Form1.Man.Text = "Pulsar" Then
Form1.Lev.Items.Clear()
instead of
Public Sub LevListAdd()
Form1.Lev.Items.Clear()
If Form1.Man.Text = "Pulsar" Then
And you should separate the calls from the man and unit ComboBoxes.
Private Sub Unit_SelectedIndexChanged_1(sender As Object, e As EventArgs) Handles Units.SelectedIndexChanged
' Do something
End Sub
Private Sub Man_SelectedIndexChanged_1(sender As Object, e As EventArgs) Handles Man.SelectedIndexChanged
Form1.Lev.Items.Clear()
Select Case Form1.Man.Text
Case "Pulsar"
With Form1.Lev.Items
.Add("Ultra Range")
.Add("IMP Range")
.Add("Twin Range")
End With
Case "animals"
With Form1.Lev.Items
.Add("dogs")
.Add("cats")
.Add("birds")
End With
End Select
End Sub

Related

Changing typing behavior of ListBox

When typing into a listbox the listbox scrolls to the next item with first letter matching the input character. I want to disable/change this behavior.
I implemented a handler for the keypress event and implemented my new behavior, but I don't see any way to remove the old behavior.
How can I disable the default behavior?
Here is the event handler for the keypress event:
Private Sub FooListBox_KeyPress(sender As Object, e As KeyPressEventArgs) Handles FooListBox.KeyPress
If SearchResetTimer.Enabled Then
SearchResetTimer.Stop()
SearchTimer.Stop()
Else
BeginUpdate()
SearchedString = ""
End If
SearchedString = SearchedString & e.KeyChar
SearchResetTimer.Start()
SearchTimer.Start()
End Sub
Private Function SearchFor(listbox As ListBox, target As String) As Integer
For i As Integer = listbox.SelectedIndex To listbox.Items.Count - 1
If listbox.Items(i).ToString().ToLower().StartsWith(target) Then
Return i
End If
Next
For i As Integer = 0 To listbox.SelectedIndex - 1
If listbox.Items(i).ToString().ToLower().StartsWith(target) Then
Return i
End If
Next
Return -1
End Function
Private Sub SearchTimer_Tick(sender As Object, e As EventArgs) Handles SearchTimer.Tick
SearchTimer.Stop()
Dim Found As Integer = SearchFor(FooListBox, SearchedString)
If Found <> -1 Then
FooListBox.SelectedIndex = Found
End If
EndUpdate()
End Sub
Private Sub SearchResetTimer_Tick(sender As Object, e As EventArgs) Handles SearchResetTimer.Tick
SearchResetTimer.Stop()
End Sub
Quick overview: there are two timers, searchTimer that when ticked searches for the string and updates the control, searchResetTimer which resets the searched string and marks the beginning of a new user input.
Note that I am not releasing this code under CC, it is for illustration purposes only

How to get the name of a button that's clicked outside it's individual event procedure

I'm pretty new to Visual Basic so sorry if I happen to use the wrong wording.
I have a lot of small buttons on a single form, and was wondering if there was a uniform way to get the name of a button when it's clicked. Since there are so many buttons, I would like to not have to code each individual button to do what I want but instead have 1 method that gets the name of the button when its clicked, and from the name does something. I'm not sure if this is possible at all, but it would make my program much simpler.
Create only one event handler for all buttons
Private Sub Button_Click(sender As Object, e As EventArgs)
Dim button As Button = DirectCast(sender, Button)
Dim name As String = button.Name
' use name
End Sub
Then you can "attach" this handler to all buttons in the constructor
Public Sub New()
InitializeComponents()
AddHandler button1.Click, AddressOf Button_Click
AddHandler button2.Click, AddressOf Button_Click
AddHandler button3.Click, AddressOf Button_Click
' ...
End Sub
Or use "less readable", in case of big amount of controls, approach - Handles keyword
Private Sub Button_Click(sender As Object, e As EventArgs) Handles button1.Click,
button2.Click,
button3.Click,
button4.Click
' code
End Sub
Usually eventhandlers provide instance of the control which raised an event - sender
Because type of the parameter is object you need cast parameter to the type you expected and use it.
If your button naming could be done programmatically then maybe you should be creating the buttons programmatically. I had a similar problem with text boxes. here is a part of the code I used to generate them on the fly. Perhaps you could use it as a model to create buttons on the fly.
Private Class cCell
Private value As Integer
Private cellTB As TextBox
Public Sub New(ByVal idx As Integer, ByVal col As Integer, ByVal row As Integer)
value = 0
cellTB = mkTB(idx, col, row)
Form1.Controls.Add(cellTB)
End Sub
Private Function mkTB(ByVal idx As Integer, ByVal col As Integer, ByVal row As Integer)
Dim tb As New TextBox
tb.Top = Form1.cMargin + row * (Form1.cUnit + Form1.cMargin) + Int(row / 3) * Form1.cMargin * 3
tb.Left = Form1.cMargin + col * (Form1.cUnit + Form1.cMargin) + Int(col / 3) * Form1.cMargin * 3
tb.Width = Form1.cUnit
tb.Height = Form1.cUnit
tb.Name = "cellTB" & idx.ToString
tb.Text = ""
AddHandler tb.TextChanged, AddressOf cCell_TextChanged
Return tb
End Function
Private Sub cCell_TextChanged() ' change text event handler for the cells textbox
If IsNumeric(cellTB.Text) Then
If cellTB.Text > 9 Or cellTB.Text < 1 Then
cellTB.Text = ""
Else
cellTB.Font = New Font(cellTB.Font, FontStyle.Bold)
cellTB.ForeColor = Color.Black
value = cellTB.Text
trimPList()
End If
Else
cellTB.Text = ""
End If
End Sub
End Class
Private Sub mkCells()
Dim idx As Integer
Dim col As Integer
Dim row As Integer
For idx = 0 To 80
row = Int(idx / 9)
col = idx Mod 9
aCells(idx) = New cCell(idx, col, row)
Next
End Sub

Validating textbox when enter button is pushed

I'm creating a AddIn for Autodesk Inventor (3D drawing software), and for the moment I am playing with positional constraints.
I created a custom user menu for quick editing certain values, in this case the elevation and orientation value.
First I used the textbox.textchanged event to change my constraint value. But this was working not 100%. Example when pressing elevation 1000 would change the elevation 4 times ( on per digit ).
Now I went to using the validated event. This works better, BUT I would like to have the textbox to initiate validation when the Enter button is pressed. For this I whipped up this, but it's not correct i'm sure of it. How should I write this correctly?
The code below works but, I would like to have a proper way to achieve the result.
Private Sub tbElevationValue_TextChanged(sender As Object, e As EventArgs) _
Handles tbElevation.Validated
' If the elevation parameter and textbox value are the same
' The sub must be aborted
If CDbl(tbElevation.Text) = oElevationParameter.Value * 10 Then Exit Sub
' Check the entered value
Dim oValue As Double
If tbElevation.Text = "" Then
oValue = 0
tbElevation.Text = 0
Else
oValue = tbElevation.Text
End If
' Set the parameter value
oElevationParameter.Value = oValue / 10
' Update the document
EM_AddIn.StandardAddInServer.m_inventorApplication.ActiveDocument.Update()
End Sub
Private Sub tbOrientation_TextChanged(sender As Object, e As EventArgs) _
Handles tbOrientation.Validated
' If the orientation parameter and textbox value are the same
' The sub must be aborted
If CDbl(tbOrientation.Text) = cRandiansToDegrees(oOrientationParameter.Value) Then Exit Sub
' Check the entered value
Dim oValue As Double
If tbOrientation.Text = "" Then
oValue = 0
tbOrientation.Text = 0
Else
oValue = tbOrientation.Text
End If
' Set the parameter value
oOrientationParameter.Value = cDegreesToRandians(oValue)
' Update the document
EM_AddIn.StandardAddInServer.m_inventorApplication.ActiveDocument.Update()
End Sub
Private Sub OrientationElevationEnterKey_Pressed(sender As Object, e As Windows.Forms.KeyEventArgs) Handles tbElevation.KeyUp, tbOrientation.KeyUp
If e.KeyCode = Windows.Forms.Keys.Enter Then
CType(sender, Windows.Forms.TextBox).Parent.Focus()
CType(sender, Windows.Forms.TextBox).Focus()
End If
End Sub
I think you're on the right way. It can be a pain to register a key_down event for each TextBox object, but your idea is good.
You can set a key_down event listener to your form instead.
Try something like this:
Private Sub Main_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
If e.KeyCode = Keys.KeyCode.Enter Then
MyBase.Focus() ' this will cause the currently focused control to validate
End If
End Sub

Is this program efficient

I've put together a small calculator application that works quite well, but despite being a novice to VB.net I know that the program probably isn't as efficient as it should be. The idea is that upon inputting numbers into a textbox and pressing a mathematical operator, the textbox will reset and continue the equation, storing the past values entered.
Dim input1 As Double
Dim numfunction As Double
'numerical functions (null = 0, add = 1, subtract = 2, divide = 3, multiply = 4)
Private Sub btnAdd_Click(sender As Object, e As RoutedEventArgs) Handles btnAdd.Click
If txtNum.Text = "" Then
MsgBox("Please enter a number")
Else
numfunction = 1
input1 = input1 + txtNum.Text
txtNum.Text = ""
End If
End Sub
Private Sub btnEqual_Click(sender As Object, e As RoutedEventArgs) Handles btnEqual.Click
If txtNum.Text = "" Then
MsgBox("Please enter a final number")
End If
If numfunction = 1 Then
txtNum.Text = txtNum.Text + input1
input1 = 0
End If
End Sub
Could you point me in the right direction as to what I should replace add or remove to make my programs more efficient in the future? Keep in mind that the BtnAdd_Click event is just one of 4 (add, sub, divide, multiply) and because of that btnEqual_Click will have a few if statements, checking for what function the user has put in, and if there is anything in txtNum at all.
Thanks in advance, I'm not asking for anyone to complete my code, but I'd love to see what options I have so I make more efficient programs in the future.
With a little initial effort you could simplify this task by using the power of object oriented programming:
Public Class Form1
' hold a reference to all operations in a list of operations
Private _operations As New List(Of Operation)
' the operation currently choosen
Private Property _currentOperation As Operation
' the 2 numbers you want to perform the operations on
Private _number1 As Double = 0
Private _number2 As Double = 0
Public Sub New()
InitializeComponent()
SetupOperations()
TextBox1.Text = 0
End Sub
Public Sub ChangeOperation(operation As Operation)
_number1 = _currentOperation.FunctionDelegate.Invoke(_number1, _number2)
TextBox1.Text = _number1
_currentOperation = operation
End Sub
Private Sub SetupOperations()
_operations.Add(New Operation(Me, btnAdd, Function(x, y)
Return x + y
End Function))
' heres the crux ... you use anonymous method to define your functions hook them to the form (Me) and the related Button
' all at once
' Similar for the other operations (subtract / multiply / divide / pow, and so on)
Dim equalsOperation As New Operation(Me, btnEqual, Function(x, y)
Return y
End Function)
_operations.Add(equalsOperation)
_currentOperation = equalsOperation
End Sub
' for this example i used only one textbox and a lable indicating wheter the number entered is a valid double
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
Dim result As Double
If Double.TryParse(TextBox1.Text, result) Then
_number2 = result
lblValid.Text = "Valid" ' tell the user that the number entered is valid or not
Else
lblValid.Text = "Invalid"
End If
End Sub
''' <summary>
''' An Operation that hooks up a button click and can execute the operation
''' </summary>
Public Class Operation
Private _owningForm As Form1
Public Property FunctionDelegate As Func(Of Double, Double, Double) ' use a delegate to a Func that returns double with 2 double parameters
Public Sub New(owningForm As Form1, boundButton As Button, functionDelegate As Func(Of Double, Double, Double))
Me.FunctionDelegate = functionDelegate
Me._owningForm = owningForm
AddHandler boundButton.Click, AddressOf boundButton_Click ' make the operation hook up on the click event
End Sub
Private Sub boundButton_Click()
_owningForm.ChangeOperation(Me)
End Sub
End Class
End Class
Hope this is not too confusing for you, I intended to show you a bigger world than simple routines and tons of eventhandlers
You could simplify your code by inserting your checking code into a separate subroutine.
Sub CheckVals()
If txtNum.Text = "" Then
MsgBox("Please enter a final number")
End If
If numfunction = 1 Then
txtNum.Text = txtNum.Text + input1
input1 = 0
End If
End Sub
You would then reference this sub from your two button click events.
Private Sub btnAdd_Click(sender As Object, e As RoutedEventArgs) Handles btnAdd.Click
CheckVals()
End Sub

vb.net Find Form

In the Windows, the native Notepad program has a find form. Basically When the user types and hits 'Find Next', the program proceeds to find the text while keeping the focus on the Find form. This way the user can keep hitting the 'Enter' key or the button and still have the text highlighted while the form is focused.
My problem is that I have a different form for the "Search" feature and whenever the user hits "Enter" the text is found and the focus is set on the TextBox but when the user hits "Enter" again, the text gets edited because of the focus.
Currently, I'm using Regex to do this and I am using a WPF TextBox using HostElement:
Private Function GetRegExpression() As Regex
Dim result As Regex
Dim regExString As [String]
regExString = txtbx_Find.Text
If matchCaseCheckBox.Checked Then
result = New Regex(regExString)
Else
result = New Regex(regExString, RegexOptions.IgnoreCase)
End If
Return result
End Function
Private Sub FindText()
''
Dim WpfTest1 As New SpellPad.Tb
Dim ElementHost1 As System.Windows.Forms.Integration.ElementHost = frm_Menu.Controls("ElementHost1")
Dim TheTextBox As System.Windows.Controls.TextBox = CType(ElementHost1.Child, Tb).ctrl_TextBox
''
If isFirstFind Then
regex = GetRegExpression()
match = regex.Match(TheTextBox.Text)
isFirstFind = False
Else
match = regex.Match(TheTextBox.Text, match.Index + 1)
End If
If match.Success Then
Dim row As Integer = TheTextBox.GetLineIndexFromCharacterIndex(TheTextBox.CaretIndex)
MoveCaretToLine(TheTextBox, row + 1)
TheTextBox.SelectionStart = match.Index
TheTextBox.SelectionLength = match.Length
TheTextBox.Focus()
Me.Focus()
Else
MessageBox.Show([String].Format("Cannot find ""{0}"" ", txtbx_Find.Text), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information)
isFirstFind = True
End If
End Sub
Private Sub btn_FindNext_Click(sender As Object, e As EventArgs) Handles btn_FindNext.Click
''
Dim WpfTest1 As New SpellPad.Tb
Dim ElementHost1 As System.Windows.Forms.Integration.ElementHost = frm_Menu.Controls("ElementHost1")
Dim TheTextBox As System.Windows.Controls.TextBox = CType(ElementHost1.Child, Tb).ctrl_TextBox
''
FindText()
'theTextBox.Focus()
End Sub
I want it to be just like Notepad where the user hits "Enter" and keeps focus on the Find Form while selecting the text. How can this be achieved?
I think you should catch "keyup" event of your form like this :
Class MainWindow
Private Sub Window_KeyUp(sender As System.Object, e As System.Windows.Input.KeyEventArgs) Handles MyBase.KeyUp
If e.Key = Key.Enter Then
FindNext()
End If
End Sub
Private Sub btn_FindNext_Click(sender As Object, e As EventArgs) Handles btn_FindNext.Click
FindText()
End Sub
Private Sub FindNext()
''
Dim WpfTest1 As New SpellPad.Tb
Dim ElementHost1 As System.Windows.Forms.Integration.ElementHost = frm_Menu.Controls("ElementHost1")
Dim TheTextBox As System.Windows.Controls.TextBox = CType(ElementHost1.Child, Tb).ctrl_TextBox
''
FindText()
'theTextBox.Focus()
End Sub
End Class