Use a variable to select a label - vb.net

Hear is my code. I uses this code 92 times. What I would like to do is create a sub and call it sending a variable to control a label. So instead of label92.text it would be something like label(labelnum).text.
Case 92
If Label92.Text = "" Then Label92.Text = DataHold(92, 7)
If Int(Label92.Text) = Int(DataHold(92, 7)) Then
Label92.ForeColor = Color.Black
Label92.Text = DataHold(92, 7)
End If
If Int(Label92.Text) < Int(DataHold(92, 7)) Then
Label92.ForeColor = Color.Red
Label92.Text = DataHold(92, 7)
End If
If Int(Label92.Text) > Int(DataHold(92, 7)) Then
Label92.ForeColor = Color.LightBlue
Label92.Text = DataHold(92, 7)
End If

You can use the Controls.Find method:
Dim labelNum As Integer = 92
Dim lbl As Label = Controls.Find("Label" & labelNum, True).FirstOrDefault
If lbl IsNot Nothing Then
'Do something with lbl, which is Label92
End If
Side note: That's a lot of labels. Do consider using other controls, such as a DataGridView or a ListView control, etc. or just paint the information. Or more to the point, a user using your program is probably not getting a great user experience by looking at that much information on the screen. Try to reduce it and only show pertinent information.

Related

Dynamic entries from textfiles into FlowLayoutPanel

I'm currently working on a ToDo program, where you can simply add notes. (With the option to set priority and attachment) The Note will be saved as a textfile. Now I want to make an over view of the ToDo's which have to be done. In the end it's supposed to look like a list, one row for each Note, built like this:
TITLE.............................[Attachment Icon]..[Priority Icon]..[CheckBox]
The checkbox should always be on the very right side of the row.
My idea is to add a FlowLayoutPanel to a FlowLayoutPanel for every Note. In the child-FlowLayoutPanel I'll add the controls. My problem is that I have no Idea how to set the positions of the controls. I tried to add a label and use it as a space between the title and the other controls, but it doesn't really work.
Here's the code I currently have:
For Each File In Directory.GetFiles(myPath)
Dim tlp As New FlowLayoutPanel
tlp.BackColor = Color.Gray
tlp.Width = 260
tlp.FlowDirection = FlowDirection.TopDown
Dim lbl As New Label
lbl.AutoSize = True
lbl.Text = getInsert(File, 0)
lbl.Anchor = AnchorStyles.Right
lbl.ForeColor = Color.White
AddHandler lbl.Click, Sub() Me.getInsert(File, 0)
tlp.Height = 40
Dim cbx As New CheckBox
cbx.FlatStyle = FlatStyle.Flat
cbx.Text = ""
cbx.Width = 15
cbx.Height = 30
AddHandler cbx.CheckStateChanged, Sub() Me.deleteEntry(tlp)
Dim space As New Label
space.AutoSize = False
space.Text = ""
space.Height = 30
space.Anchor = AnchorStyles.Right
tlp.Controls.Add(lbl)
tlp.Controls.Add(Space)
tlp.Controls.Add(cbx)
Space.Width = tlp.Width - lbl.Width - cbx.Width - 15
mfp.Controls.Add(tlp)
Next
Here's an example:
todo_example
I hope anyone has a good idea how to solve this problem.
Thanks in advance :)

What method would make this code more efficient or proper?

I have a program that collects information based on the radio buttons that are checked, as well as a checkbox.
Private Sub calculateBtn_Click(sender As Object, e As EventArgs) Handles calculateBtn.Click
Dim TypeCost As Integer
Dim ColorCost As Integer
Dim Foldable As Integer
If standardRbtn.Checked() Then
TypeCost = 99
End If
If deluxRbtn.Checked() Then
TypeCost = 129
End If
If premiumRbtn.Checked() Then
TypeCost = 179
End If
If blueRbtn.Checked() Then
ColorCost = 0
End If
If redRbtn.Checked() Then
ColorCost = 10
End If
If pinkRbtn.Checked() Then
ColorCost = 15
End If
If foldableCheckBox.Checked() Then
Foldable = 25
Else
Foldable = 0
End If
Dim Price As String = TypeCost + ColorCost + Foldable
priceTextBox.Text() = "$" & Price
End Sub
I have a strong feeling that this code can be simplified, but I just can't seem to think of what it is. My friend suggested Enumerations and Arrays, but I don't think those would work. Would they?
I have been searching around for a question similar to this for a while now.
I would also like to point out that the type radio buttons and the color radio buttons are in separate group boxes, so they function separately. Making it impossible for more than one type or color to be selected at the same time.
I have uptade the code to:
If standardRbtn.Checked() Then
TypeCost = 99
ElseIf deluxRbtn.Checked() Then
TypeCost = 129
ElseIf premiumRbtn.Checked() Then
TypeCost = 179
End If
If blueRbtn.Checked() Then
ColorCost = 0
ElseIf redRbtn.Checked() Then
ColorCost = 10
ElseIf pinkRbtn.Checked() Then
ColorCost = 15
End If
If foldableCheckBox.Checked() Then
Foldable = 25
Else
Foldable = 0
End If
I knew there was something extremely simply I would be able to do to sort of get rid of some of the repetitiveness. Thank you, phatfingers.
If there's any other ideas anyone would like to throw out, I would love to hear them. But this solution is good enough for me.
I simply went from using a bunch of if statements to "ElseIf". The updated code is in the original thread. :) - Thank you to phatfingers for the idea.
You could use a dropdown, which would probably be the lowest effort solution and allow you to dynamically add new options without rewriting anything.
You can then just fetch the value of the selected item.
https://forums.asp.net/t/988528.aspx?Dynamically+adding+items+in+DropDownList
So something like:
Private Sub OnFormLoad() //I forgot the exact name of the load event of the form and what it looks like
typeDropDown.Items.Add(New ListItem("Standard", "99"))
typeDropDown.Items.Add(New ListItem("Premium", "129"))
typeDropDown.Items.Add(New ListItem("Deluxe", "179"))
colorDropDown.Items.Add(New ListItem("Blue", "0"))
colorDropDown.Items.Add(New ListItem("Red", "10"))
colorDropDown.Items.Add(New ListItem("Pink", "15"))
End Sub
Private Sub calculateBtn_Click(sender As Object, e As EventArgs) Handles calculateBtn.Click
Dim Price as String = typeDropDown.SelectedValue + _
colorDropDown.SelectedValue + _
iif(foldableCheckBox.Checked(), 25, 0)
priceTextBox.Text() = "$" & Price
End Sub

ArgumentOutOfRangeException when trying to clear combobox

I'm having the following error message appear when trying to run .Clear() on my combobox:
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.Windows.Forms.dll
{"InvalidArgument=Value of '-1' is not valid for 'index'.
Parameter name: index"}
The strange part is, it does the .Clear() before going to the new 'page' in the application, and it works without a problem. Once I'm on the 'page', draw the items in the combobox and try to go to the next 'page' of the application, it calls the function with the clear once again and blows up when it gets to the .Clear(). If I comment out the cbo.DrawMode = DrawMode.OwnerDrawFixed in the code below it also runs as normal, so the problem is definitely with drawing the strings in the combobox (I'm drawing the strings to change the colour of them). Anyways, completely stumped as to how to fix this, any help would be appreciated.
Code is below:
-My clear method
Public Sub ClearCombos()
'Clear Applicant Combos
cboPrimary.Items.Clear() 'crashes when it hits this line
cboJoin1.Items.Clear()
cboJoin2.Items.Clear()
cboJoin3.Items.Clear()
cboJoin4.Items.Clear()
End Sub
Drawing the strings in the comboboxes
Sub CheckForAgeOverage()
c_applicants = {cboPrimary, cboJoin1, cboJoin2, cboJoin3, cboJoin4}
Dim curdate As Date = Date.Now
Dim age As Integer
counter = 0
'Check age of applicants
For Each cbo As ComboBox In c_applicants
If CKeyValuePair.GetComboBoxSelectedKey(c_applicants(counter), True) = instApplicant.applicantId Then
age = Math.Floor(DateDiff(DateInterval.Month, DateValue(instApplicant.BirthDate), curdate) / 12)
If age >= 70 Then
overArray.Add(CKeyValuePair.GetComboBoxSelectedValue(c_applicants(counter)))
End If
cbo.DrawMode = DrawMode.OwnerDrawFixed
Else
For Each j As JoinsBU In instJoins
If CKeyValuePair.GetComboBoxSelectedKey(c_applicants(counter), True) = j.Applicant.applicantId Then
age = Math.Floor(DateDiff(DateInterval.Month, DateValue(j.Applicant.BirthDate), curdate) / 12)
If age >= 70 Then
overArray.Add(CKeyValuePair.GetComboBoxSelectedValue(c_applicants(counter)))
End If
cbo.DrawMode = DrawMode.OwnerDrawFixed
End If
Next
End If
counter += 1
Next
End Sub
The Comboboxes DrawItem event:
Private Sub cbo_DrawItem(sender As System.Object, e As System.Windows.Forms.DrawItemEventArgs) Handles cboPrimary.DrawItem, cboJoin1.DrawItem, cboJoin2.DrawItem, cboJoin3.DrawItem, cboJoin4.DrawItem
Dim brush As Brush = Brushes.Black
Dim text As String = (CType(sender, ComboBox)).Items(e.Index).ToString()
counter = 0
For Each s As String In overArray
If text = overArray(counter) Then
brush = Brushes.Red
Else
brush = Brushes.Black
End If
counter += 1
Next
e.Graphics.DrawString(sender.Items(e.Index).ToString(), e.Font, brush, _
e.Bounds, StringFormat.GenericDefault)
counter = 0
End Sub
It looks like this shouldn't happen, but it obviously is. The actual error might be in this line in the DrawItem handler:
Dim text As String = (CType(sender, ComboBox)).Items(e.Index).ToString()
Try separating the assignment out of the Dim statement, and check the value of e.Index to make sure it is non-negative. If that's the problem, you could probably work around it with an if to make sure e.Index is non-negative.

Have multiple objects in a With statement in VB?

I have a lot of labels in VB that I use in With statement to set their properties.
Problem
Is there any way I can do something like the following:
With lblA, lblB, lblC
.fontColor = color.Red
End With
Is this possible, or do I have to manually do a With statement for each of them?
There is a shorter and more readable version of your solution:
For Each lbl As Label In {lblA, lblB, lblC}
With lbl
'...
End With
Next
I would keep those types of items in a list and then apply a for each loop on them, assuming they are all of the same type (or at least base type). Assuming you are using controls of type label this would be a solution. Note that I've modified .fontColor to .ForeColor so that this example works with the Label class:
Dim lblList as new List(of Label) ({lblA, lblB, lblC})
lblList.ForEach(sub(x) x.Fore Color = color.red)
Since you've posted your solution, you could still do the following to avoid the iteration loop over the array you made (which is why I do this as a list) not having to take into account the array size or anything:
lblList.ForEach(Sub(x)
With x
.BackColor = Color.Black
.Dock = DockStyle.Top
.TextAlign = ContentAlignment.MiddleCenter
End With
End Sub)
Here is the way I ended up doing it:
Dim arrayMe As Label() = {lblA, lblB, lblC}
For count = 0 To arrayMe.Length - 1 Step 1
With arrayMe(count)
.BackColor = Color.Black
.Dock = DockStyle.Top
.TextAlign = ContentAlignment.MiddleCenter
End With
Next
There are other ways to do it, but I found this to be useful.

How can I create a loop that reveals a certain number of labels?

I want to be able to reveal and then populate a certain number of labels. The inefficient way would be to SELECT CASE on the number of labels required and then populate these in turn. I am looking for something like this:
For i = 1 to RequiredNumOfLabels
Label & i.visible = true
Label & i.text = DataTable.Rows(i).Item(2)
Next
Thank you.
EDIT:
For i = 1 To NumberOfItems
Dim lbl = Controls("lbl" & i)
lbl.Visible = True
lbl.Text = CStr(DataTable.Rows(i).Item(2))
Next
I think the line
Dim lbl = Controls("lbl" & i)
is the problem as after the line is executed, lbl still equals nothing.
The reasoning behind it is that I was trying to create an invoice generator in vb.net and I was hoping that this would be a simple way to do it - count the amount of items in the order, populate the labels with the names of the items, reveal that many labels.
If your label controls are really in order like that, you can try just referencing them from a list:
Dim myLabels As New List(Of Label)
myLabels.Add(Label1)
myLabels.Add(Label2)
Then just update them:
For i as Integer = 1 to myLabels.Count
myLabels(i - 1).Visible = True
myLabels(i - 1).Text = DataTable.Rows(i).Item(2).ToString
Next
You can get controls by name through the forms Controls property
For i = 1 To RequiredNumOfLabels
Dim lbl = TryCast(Controls("Label" & i), Label)
If lbl IsNot Nothing Then
lbl.Visible = True
lbl.Text = CStr(DataTable.Rows(i).Item(2))
End If
Next
Since you get an object of type Control, you have to cast it to Label.
UPDATE
It seems that you only use properties that are defined in Control anyway. Therfore you can simplify the code to
For i = 1 To RequiredNumOfLabels
Dim lbl = Controls("Label" & i)
lbl.Visible = True
lbl.Text = CStr(DataTable.Rows(i).Item(2))
Next