Check state of checkboxes in an array - runtime error - arrays

I want to run one block of code when any of the 197 checkboxes on the form are clicked. I have all of the checkboxes in an array which I used to check the availability of each seat on the forms load (this program is a seat booking system). Each seat is a checkbox displayed as a button, and I would like the "Seats selected" label to show the seat selected once it has been checked. I used the same array in the code below to check whether they were checked, and if they were the label would be updated. The code below is giving me an error described as "Object reference not set to an instance of an object" when I click one of the checkboxes. I'm not sure why this is and I can't really find a solution. I am only coding the first three checkboxes at the moment, just to see if it works. Ideally I would like to list all 197 checkboxes as handles to this procedure, so when any are clicked every seats checkstate will be checked.
If anyone has a solution that would be great! Thanks.
Public Class frmSeatPlan
Dim seat(11, 20) As Control
Private Sub A1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles A1.CheckedChanged, A2.CheckedChanged, A3.CheckedChanged
seat(1, 1) = A1
seat(1, 2) = A2
seat(1, 3) = A3
For y = 1 To 1
For x = 1 To 3
Dim seat(y, x) As CheckBox
If seat(y, x).Checked = True Then
selectedSeats = selectedSeats & seat(y, x).Name & ", "
MsgBox(selectedSeats)
lblSelected.Text = selectedSeats
End If
Next x
Next y
End Sub

Are you going to write handles clause 197 times? Can you be sure by the time you finished you did not make a mistake? What if you add a seat #198 between #156 and #157 - how would you go around it? You are gradually planning a maintenance nightmare for yourself. Instead, you should bind events in code, where you would also create those checkboxes. This way you will never have the problem you were getting.
For y = 1 to 3
For x = 1 to 3
Dim chk As New CheckBox
'set positioning on the screen
chk.X = x
chk.Y = y
AddHandler chk.CheckedChanged, AddressOf Any_CheckedChanged
Next
Next
Ideally, you will not need your array as well, i.e. seat(y, x), because every seat can be assigned X and Y when they are created and pass those as event arguments (so you probably will need a custom event).

Related

Control marking of a checkbox in datagridview. vbnet 2015

Best regard. I'm trying to do a validation before marking a check box in a cell of a datagridview. If a condition is met, the check must be marked, otherwise not.
The event in the grid that I am validating is CellContentClick and the code is this
Private Sub dgvDetalle_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgvDetalle.CellContentClick
If dgvDetalle.RowCount > 0 Then
Dim DifMinutes As Double = 0
DifMinutes = DateDiff("n", CDate(dgvDetal(20, e.RowIndex).Value), Date.Now)
If DifMinutes > 60 Then
If dgvDetal.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = True Then
TotalSP = TotalSP + 1
Else
TotalSP = TotalSP - 1
End If
else
'Here should go the code so that the check of the datagridview is not marked
End If
End If
End Sub
The language I use is VB.NET from VS 2015
Thank you very much for your help.
The event in the grid that I am validating is CellContentClick but the check of the datagridview is always selected. I have not found the instruction to cancel the event.
I solved adding the following instructions
dgvDetal.EndEdit()
dgvDetal.CurrentRow.Cells(23).Value = 0
dgvDetal.RefreshEdit()

Changing control (that is in an array) from a timer: Not working

I'm trying to make a picture's visibility toggle on a timer. The picture I am trying to change is underscore(i). Here is that code:
Dim DigitSelected As Integer = 1
Public Underscores(3) As PictureBox
....
Private Sub CursorTimer_Tick(sender As System.Object, e As System.EventArgs) Handles CursorTimer.Tick
Me.Underscores(DigitSelected).Visible = Not (Me.Underscores(DigitSelected).Visible)
End Sub
This code above was previously working, but recently I moved where I was creating the pictureboxes and their stuff to a module on another page:
With Initials
For i As Byte = 1 To 3
.Underscores(i) = New PictureBox
With .Underscores(i)
.Height = 60
.Width = 144
.ImageLocation = "Underscore.png"
.BackColor = Color.Transparent
End With
.Controls.Add(.Underscores(i))
Next
end with
Now when I use the top-most snippet of code, it throws no errors, and changes nothing. I'm pretty sure I'm just missing something small.
Any ideas? Thanks!
I don't exactly know what you are trying to achieve here, but here is what happens :
Everytime you run that loop, you create three transparent PictureBox that you add to your Main Form. You don't remove anything, nor hide anything !
If you want to toggle visibility, that is no way of doing so !
The best would be for you to know the PictureBoxes names, so you can do :
Dim pb1 = CType(Initials.FindControl("MyPictureBox", true), PictureBox)
If Not IsNothing(pb1) Then
pb1.Visible = Not pb1.Visible
End If

How do you create a sort of on click event (i think that's what its called) in Visual Basic?

So i have a button (lets call it apples) which, when clicked i would like to add one apple to be displayed in a list box. if clicked again it would then add another, so on. then i could tally up an order on the list box.
Public Class frmCafe
Const price_cheese_burger As Double = 4.95
Const price_blt_sandwich As Double = 4.0
Const price_ht_sandwich As Double = 3.5
Dim total As Double
Private Sub btnCheeseB_Click(sender As Object, e As EventArgs) Handles btnCheeseB.Click
'here when i click cheeseburger, id like it to +1 to the list order (lstChosenProducts)
'just struggling to figure it out
End Sub
Don't now if this helps or if it makes much sense, but any input would be great, cheers!

Control Array Examples Needed for Visual Studio 2013

I know control arrays don't actually exist anymore, but I need something I can relate to my code. I'm making a shopping list game with a grid of 32 tiles that flip when clicked. They are actually PictureBoxes called pbxTile1 - pbxTile32. I sense you already know what I'm going to say.
A sample of my code:
Private Sub pbxTile1_Click(sender As Object, e As EventArgs) Handles pbxTile1.Click
If TileFlag(1) = 0 Then Exit Sub
My.Computer.Audio.Play(My.Resources.Tile_Flip, AudioPlayMode.Background) : Application.DoEvents()
Me.pbxTile1.BackgroundImageLayout = ImageLayout.Stretch
Me.pbxTile1.BackgroundImage = My.Resources.FLIP01 : Application.DoEvents() : System.Threading.Thread.Sleep(50)
Me.pbxTile1.BackgroundImage = My.Resources.FLIP02 : Application.DoEvents() : System.Threading.Thread.Sleep(50)
Me.pbxTile1.BackgroundImage = My.Resources.FLIP03 : Application.DoEvents() : System.Threading.Thread.Sleep(50)
Dim GroceryValue = TileItem(1)
Call Get_Grocery(GroceryValue)
Me.pbxTile1.BackgroundImageLayout = ImageLayout.None
Me.pbxTile1.BackgroundImage = My.Resources.ResourceManager.GetObject(GroceryResource) : Application.DoEvents()
You can see my problem - this is a fraction of the subroutine, which I need to recreate 32 times. But I'm sure one of you bright lads can come up with something to make it much less painful for me! I've seen tagging, and lists, and indexing - but not sure how to apply it, which is best, and need some examples please!
It's ok, I've found it! My word it works perfectly:
I didn't realise that Event Handlers can handle multiple Controls!
Instead of duplicating my code (32 times!) I just changed the Sub to:
Private Sub pbxTile_Click(ByVal sender As Object, e As System.EventArgs) Handles pbxTile1.Click, pbxTile2.Click, pbxTile3.Click, pbxTile4.Click, pbxTile5.Click, pbxTile6.Click, _
pbxTile7.Click, pbxTile8.Click, pbxTile9.Click, pbxTile10.Click, pbxTile11.Click, pbxTile12.Click, pbxTile13.Click, pbxTile14.Click, pbxTile15.Click, pbxTile16.Click, _
pbxTile17.Click, pbxTile18.Click, pbxTile19.Click, pbxTile20.Click, pbxTile21.Click, pbxTile22.Click, pbxTile23.Click, pbxTile24.Click, pbxTile25.Click, pbxTile26.Click, _
pbxTile27.Click, pbxTile28.Click, pbxTile29.Click, pbxTile30.Click, pbxTile31.Click, pbxTile32.Click
So basically if any of the 32 boxes are clicked, it calls the same Sub. And to differentiate between each PictureBox (this is the bit I was REALLY stuck on) I used DirectCast:
For z = 1 To 32
If DirectCast(sender, PictureBox).Name = "pbxTile" & z And TileFlag(z) = 0 Then Exit Sub
Next
I'm not sure if this is the most streamlined way, but it certainly works a treat, and saved me a bunch of code I didn't need!

Tying ComboBox/NumericUpDown selections to an array?

I'm working on a VB project that has a lot of comboboxes and numericupdown items.
Lets say we have ComboBox1, 2, 3, 4, and 5; and we have NumericUpDown1, 2, 3, 4, 5.
When the user clicks the "Save" button, I want to save all of their selected combobox items and numericupdown numbers to a CSV file. Is there an elegant/automatic way to tie all of the .SelectedIndex and .Value for these items to an array so I can easily write the array out to a CSV?
The only way I know to do this so far is to manually associate each one with an array position:
Arr(0) = ComboBox1.SelectedIndex
Arr(1) = ComboBox2.SelectedIndex
...
Arr(5) = NumericUpDown1.Value
Arr(6) = NumericUpDown2.Value
...
etc.
This wouldnt be too bad, except I have a LOT of these items, and writing a line for each one seems silly. I'm new to VB, so this might be an obvious solution to some. Any ideas?
Having them bound to an array would be really handy because I also allow the user to Load a CSV file, which I would like to automatically populate the ComboBoxes and NumericUpDowns from the CSV values. The only way I know to do this is to manually move each array item to the respective combobox/numeric item when they click the Load file button:
ComboBox1.SelectedIndex = Arr(0)
ComboBox2.SelectedIndex = Arr(1)
...
NumericUpDown1.Value = Arr(5)
NumericUpDown2.Value = Arr(6)
...
etc.
Edit: Here is some application info as requested...
The CSV file that can be saved/loaded looks like this:
#"Device Info","123456","asdfgh","0000","1.0x","1"
000F,0000,0032,0000,00C8,0001,0078,0101,0000,0001,0000,0001
010F,0078,0000,0103,0001,0000,000A,0005,0007,0006,0000
0001,000A,000A,000A,000A,0005,0005,0005,0002
...etc
The header line just has serial number, version, and other misc info; it is automatically generated by the target device. All of the other lines are configuration setpoints that the target device reads in and automatically configures itself. I'm writing this PC program to be able to edit (and create from scratch) these configuration CSV files with a nice GUI interface. Each item is tied to a specific setpoint, such as 000F = Language, 0032 = System Frequency, 00C8 = System Voltage, etc. The easiest way I saw to make this configuration program was to use numeric entry and drop-down comboboxes that the user can select what they want. Each NUD and CBOX equates to one of the CSV file data fields.
You can use Controls.Find() to get a reference to the desired control based on an index value. Here's a quick example to demonstrate what I mean:
For i As Integer = 1 To 30
Dim matches() As Control = Me.Controls.Find("NumericUpDown" & i, True)
If matches.Length > 0 AndAlso TypeOf matches(0) Is NumericUpDown Then
DirectCast(matches(0), NumericUpDown).Value = i
End If
Next
You can incorporate code like that into the load/save routines.
I would use binary serialization. This eliminates the need to format strings or xml when saving control properties. Similar to Plutonix's solution, it only works on certain types of control. However, it can be modified to work on any type of control - but only supports a single property to be loaded for each control. It will work on all controls of type X instead of controls named xName. You can add further restrictions by grouping the controls to be serialized in a panel or other means.
Make a new Form called Form1. Add some NumericUpDowns, TextBoxes, and ComboBoxes. Put some values in the ComboBoxes at design time, otherwise calling loadState() in Form_Load will be meaningless. However, loadState() can be called whenever (i.e. after the comboboxes have been populated).
You will need to import these two namespaces:
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
In your class:
Private Shared stateFileName As String = "SavedState.bin"
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
saveState(Me)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
loadState(Me)
End Sub
And these are the methods you will use to save and load states. The save state method:
Private Shared Sub saveState(instance As Form)
Dim controlProperties As Dictionary(Of String, Object) =
instance.Controls.OfType(Of Control).ToDictionary(Of String, Object)(
Function(c) c.Name,
Function(c)
' You can support different types of controls here too
If TypeOf c Is NumericUpDown Then
Return CType(c, NumericUpDown).Value
ElseIf TypeOf c Is ComboBox Then
Return CType(c, ComboBox).SelectedIndex
Else
' All other controls get their text property saved
' .Text is a property of Control
Return c.Text
End If
End Function)
Using myFileStream As Stream = File.Create(stateFileName)
Dim serializer As New BinaryFormatter
serializer.Serialize(myFileStream, controlProperties)
End Using
End Sub
The load state method:
Private Shared Sub loadState(instance As Form)
If File.Exists(stateFileName) Then
Using myFileStream As Stream = File.OpenRead(stateFileName)
Dim deserializer As New BinaryFormatter()
Dim controlProperties = CType(deserializer.Deserialize(myFileStream), Dictionary(Of String, Object))
For Each c As Control In instance.Controls
If controlProperties.ContainsKey(c.Name) Then
' You can support different types of controls here too
If TypeOf c Is NumericUpDown Then
CType(c, NumericUpDown).Value = CDec(controlProperties(c.Name))
ElseIf TypeOf c Is ComboBox Then
CType(c, ComboBox).SelectedIndex = CInt(controlProperties(c.Name))
Else
c.Text = controlProperties(c.Name).ToString()
End If
End If
Next
End Using
End If
End Sub
You should add exception handling, and note that a binary file is not meant to be edited by a human without the assistance of a machine.

Resources