Searching through CheckedBoxLists for checked boxes - vb.net

I am creating a simple application that would enable me to input information into some textboxes and then, after pushing a button (called Addbtn) combine those into one string. This string would be added to a checkboxlist called ConcernsChk. When one or more of these strings are completed, the user would click the appropriate checkbox and click a button (called CompleteSortBtn) which would transfer that string to another checkboxlist. The issue I'm having is that my checkboxlist items do not delete according to their checked status. They delete one at a time beginning from the top and moving down.
Here's the code in question:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles CompleteSortBtn.Click
Dim Disposition As String = ""
Dim i As Integer
If ConcernsChk.CheckedItems.Count > 0 Then
For i = 0 To (ConcernsChk.Items.Count - 1)
If ConcernsChk.GetItemChecked(i) = True Then
Disposition = ConcernsChk.Items(i)
DispositionChk.Items.Add(Disposition)
ConcernsChk.Items.Remove(Disposition)
End If
Next
Else
MessageBox.Show("Please add Concerns before marking them complete.")
End If
I keep getting an error thrown that I cannot equal 3 and I have no idea what to do from here. This is thrown whether there are 2 items in the checkboxlist or 10.
Long story short, when I push the CompleteSortBtn, I want the program to do 4 things: 1. search through ConcernChk 2. Find checked boxes 3. Send the checked boxes to DispositionChk 4. Delete the checked items from ConcernChk
My apologies for the long post and thank you for whatever help you can give.

You are iterating though items not checkeditems.... count will be different.
SINCE you are removing items from the list you ALSO need to do it bottom to top.
For i = (ConcernsChk.Items.Count - 1) to 0 step - 1
If ConcernsChk.Items(i).Checked Then
Disposition = ConcernsChk.Items(i)
DispositionChk.Items.Add(Disposition)
ConcernsChk.Items.RemoveAt(I)
End If
Next

Related

How can I cause a button click to change the image in a picture box?

I'm using VS2010 for VisualBasic, and I'm working with several similar forms. What I need to have happen is for the buttonclick on each page to cycle through the My.Resource images in order: adj_01, adj_02, adj_03,... and each form will have a different three-letter prefix.
This is what I have so far:
It might not be clear, but I'm trying to have the images cycle trough one after the other with each button click. Apparently there is an issue with either my referencing, or that the images are .png format. Simultaneously, I'm trying to have 2 separate label update information with each image change. This is what I have so far with that:
EDIT I just noticed an error that might confuse everyone on the photos: The first lines starting the If statements are checking to see if the PictureBox is empty. Needless to say, I don't know how to do that.
Here you go...
Private Sub NextAdjButton_Click(sender As Object, e As EventArgs) Handles NextAdjButton.Click
If AdjectivesPictureBox.Tag Is Nothing Then
AdjectivesPictureBox.Tag = 0
End If
Dim number As Integer = CInt(AdjectivesPictureBox.Tag)
If number < 5 Then
number = number + 1
AdjectivesPictureBox.Image = My.Resources.ResourceManager.GetObject("adj_" & number.ToString("00"))
AdjectivesPictureBox.Tag = number
End If
End Sub

Using For Loop to Check for duplicates - Error The error is: Object reference not set to an instance of an object

I have a problem that I and my limited experience cannot figure out.
I have a multi-display (form) program that is for a game show system which uses a (5) display system. As I am wrapping this project up, I have been doing some house keeping and handling some potential user errors up front.
In this instance: There is a form called GameSetup which has drop down menus that are filled via a database selection of "Teams". When a Team is selected, (10) labels are populated with registered team members. The user drags and drops a team member (ie. player) to a group of (6) labels, which will make up the active team for the game.
The problem: I wanted to have a check when a name is added to the active team roster to make sure there are no duplicates. The cleanest way to do this, I thought, would be on the .TextChanged action of the active player label and use a For loop to check the other active team player names.
Private Sub lblT1_P1_TextChanged(sender As Object, e As EventArgs) Handles lblT1_P1.TextChanged
cmdReady.BackColor = Color.Yellow
For i = 1 To 6
If i = 1 Then
' Do nothing
ElseIf Me.Controls("lblT1_P" & i.ToString).Text = lblT1_P1.Text Then 'This is the line triggering the NullException
MsgBox("This Player is already selected. Please choose another Player", MsgBoxStyle.OkOnly)
Me.Controls("lblT1_P" & i.ToString).Text = "DRAG PLAYER HERE" 'This is the other line triggering the NullException
End If
Next i
End Sub
i = 1 Do Nothing is so that it wont compare against itself (in this instance)
When I run the program (de-bug), before the form GameSetup loads, I am getting a Null Exception, which makes sense as it is looking at a form or an object in a form that is not yet initialized. Clearly, the Me.Controls is the problem, but I do not know how to handle using the integer (i) in the For Loop otherwise.
The label names are lblT1_P1 - lblT1_P6 (3 instance of each group (T1/T2/T3). I'm only dealing with T1_P1 at the moment.
Any suggestion would be greatly appreciated.
Use string.Format() to generate your control names, because it is more readable.
Instead of Me.controls("lblName").Text
use DirectCast(Me.FindControl("lblName"), Label).Text

Adding a default number of items to list box in Visual Basic

I'm working on a project for my Visual Basic class and need a nudge in the right direction. I'm not going to go into exactly what the program is supposed to do in the end because I'm not really at that point yet. The step I'm stuck on now is this.
We are supposed to have two list boxes, one for Ingredients (which I've named lstIngredients) and the second for the Recipe (lstRecipe), we are also supposed to have a text box labeled Quantity for the user to enter how many of the selected item to add to the Recipe list. For example, if the user selects "eggs" and types 3 for the quantity, "eggs" should appear 3 times in the Recipe list box. Also, if nothing is put into the quantity box, it is supposed to default to adding one of the selected item to the Recipe list box.
With the code I have written, I am able to add items to the Recipe list as long as I type something into the quantity text box, but I cannot get the program to just add one when nothing is typed into the text box. Here is the code I have so far.
Public Class Form1
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
Dim i As Integer = lstIngredients.SelectedIndex
If txtQuantity.text= "" Then
lstRecipe.Items.Add(1)
End If
Dim intCount As Integer = 0
While intCount < txtQuantity.Text
lstRecipe.Items.Add(lstIngredients.Items(i))
intCount += 1
End While
End Sub
Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click
lstRecipe.Items.Clear()
txtQuantity.Clear()
End Sub
Any help on this step would be greatly appreciated. I'm sure I'll probably have more questions as I get farther into the coding, but I will edit this question to include those when the time comes.
First, you'll need to convert the value in your Quantity text box to an integer. For that, you can use either Integer.Parse or Integer.TryParse. For instance:
Dim value As Integer = Integer.Parse(Quantity.Text)
Then you can use a For loop to add the same item that many times, for instance:
For x As Integer = 1 to value
lstRecipe.Items.Add(lstIngredients.Items(i))
Next

row cannot be programmatically added

I'm trying to populate a datagrid view with the contents af a text file i used the following code:
Private Sub Button15_Click(sender As Object, e As EventArgs) _
Handles Button15.Click
'strPath is the location of text file
Dim lines = (From line In IO.File.ReadAllLines(strPath)
Select line.Split(CChar(vbTab))).ToArray
For x As Integer = 0 To lines(0).GetUpperBound(0)
dgQuotation.Columns.Add(lines(0)(x), lines(0)(x))
Next
For x As Integer = 1 To lines.GetUpperBound(0)
dgQuotation.Rows.Add(lines(x))
Next
End Sub
But every time i run the program i get the following run time error:
Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.
Please help, I'm new to VB. Thanks in advance.
It means you either need to use data binding or add rows manually - pick one, not both.
instead of the two for loops you can just set dgQuotation.DataSource = lines ... adding values to the grid programmatically (as you do in your code) is not possible if the grid is data bound (=> DataSource is set)

How to Ommit DataGridViewRow from DataSource Based on Another Table's Data

I have a DataGridView filled with Bills from a DataTable (which is set as it's DataSource). These Bills are shown to my engineers so that they can build a Bill of Materials.
This is the SQL query which gets all my Bills:
SELECT *
FROM Bills
ORDER BY Case IsNumeric(JobNumber)
WHEN 1 THEN Replicate('0', 50 - Len(JobNumber)) + JobNumber ELSE JobNumber END
This sorts the bills by job number (some are numbers, some are strings and some are a mix of integers and characters).
Features
They can open the bill to view it (Read only) or to edit it.
Further explanation
If an engineer opens a Bill to edit it, it will be placed in a table named "OpenBills". I do this so that no other engineer can open the same bill and edit it while being worked on. The point of the OpenBills table is to determine which bill is opened. Once I know which bill is opened, I don't want it to be provided in their DataGridView when they go to edit a bill.
On the other hand, when the engineer searches for a bill to open as read-only, they should ALL be displayed (even the ones currently opened). The difference is I simply put a light blue color as the background of the row to notify the user that it is currently opened.
My current 'solution'
I am currently using a CellFormatting event on my DataGridview. In short, I verify if the current Bill being added is in my OpenBills table lst_OpenBills. If it is, then I verify if I am viewing the DataGridView as read-only or for editting mode. If it's in edit mode, I will hide the row. If it is in read-only, I will change it's back color.
Private Sub dgvBills_CellFormatting(sender As Object, e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dgvBills.CellFormatting
Dim drv As DataRowView
If e.RowIndex >= 0 Then
If e.RowIndex <= dsBOM.Tables("dtBills").Rows.Count - 1 Then
drv = dsBOM.Tables("dtBills").DefaultView.Item(e.RowIndex)
Dim c As Color
If lst_OpenBills.ContainsKey(drv.Item("PK_Bill").ToString) Then
If int_EntryPoint = 0 Then
'Read Only
c = Color.LightBlue
e.CellStyle.BackColor = c
Else
'Edit mode
dgvBills.Rows(e.RowIndex).Visible = False
End If
End If
End If
End If
End Sub
Problem with current solution
I use AlternatingRowStyles to make it easier to read. As you can see in the following comparisons, the edit mode picture should not display the alternating row styles like that. How could I ommit the DataGridViewRow from the DataTable ? Should I just re-apply the AlternatingRowStyles?
Read Only results
Edit mode
Does anyone have any solutions? Perhaps my query to get all my bills isn't appropriate ... I use the same form for both situations (read-only & edit mode). I just differentiate them using an Enum enum_EntryPoint. Any helps or suggestions is appreciated.
You could iterate through the datatable and remove the one you have selected and redraw the datagridview. Not another SQL call just using the datatable you already have. You can reinsert the row if you want, when done, or just use that same beginning datatable to refresh the DGV.
For example if the open bill was id 1287:
Dim dtTemp As DataTable = dtOpenBills.Clone()
For Each dr As DataRow in dtOpenBills.Rows
If Cint(dr("OpenBillID")) <> 1287 Then
Dim drTemp As DataRow = dtTemp.NewRow()
drTemp = dr
dtTemp.Rows.Add(drTemp)
End If
Next
DataGridViewName.DataSource = dtTemp
DataGridViewName.Refresh() 'Might not be needed
You haven't touched the original datatable.