Is there anyway to save a multiple buttons as a list? - vb.net

I am making small restaurant system project. I have 16 buttons as tables in the restaurant. I would like to change their colors or disable any of them when some events trigger (the form is loaded).
I save my button names in format TableX_ButtonY
I used a for-loop to change theirs border colors like this:
CType(Me.Controls.Find(String.Format("Table{0}Button{1}", i, x), True)(0), Button).FlatAppearance.BorderColor = Color.Blue
It will be great if I can save these buttons as a list, so I can manage it more easily.
I name their tags from 1 to 16 but I don't know how to use them correctly. Because the trigger not based on button click but rather based on the Load Form event.

Buttons are already in a collection and is a bit redundant to add them to a generic collection. In this example there are 2 buttons in a group controls collection, which could very well be any applicable container.
Dim ReservedTables() As Integer = {5, 10, 15, 20}
For Each Btn As Button In GroupBox1.Controls.OfType(Of Button)
If ReservedTables.Contains(CType(Btn.Tag, Integer)) Then
Btn.Enabled = False
End If
Next

Dim TableList As New List(Of Button)
TableList.Add(TableX_ButtonY)
For Each Table As Button in TableList
'do stuff
next
if you generated the buttons by using the designer, you can use the method you described in your question to add them all to the list

Related

Giving buttons different names through code and referring to them later on

My code creates a 5x5 grid of buttons. I am wanting to give each of these buttons different names "BtnColour1", "BtnColour2", etc. How do I give them all different names and how do I refer to each button later in the program?
Dim bytCounter As Byte
For bytCounter = 1 To 25
Dim btnColour As New Button
Me.Controls.Add(btnColour)
btnColour.Height = 50
btnColour.Width = 50
btnColour.Name = "btnColour" & bytCounter
btnColour.Enabled = False
btnColour.Left = ((bytCounter - 1) Mod 5) * 51
btnColour.Top = ((bytCounter - 1) \ 5) * 51
AddHandler btnColour.Click, AddressOf BtnClick
Your code (I guess you forgot the ending Next) does create 25 Buttons, with names btnColour1... btnColour25.
In the BtnClick event, to get the name of the clicked button, you should write something like:
Private Sub BtnClick(sender As Object, e As EventArgs)
Dim buttonName as string=CType(sender, Button).Name
'buttonName now has the clicked button name
End Sub
Of course, since you set the enabled property to False, your button click event will not fire.
In a general sense (and in addition to Spyros' answer, which is a good way to do it in an event handler - the sender is always the thing that raised the event), when you give a control a name and add it to a control's Controls collection, you can then retrieve it by that name later:
'Here you added the button to the form controls:
Me.Controls.Add(btnColour)
'later in the code you can ask for it back by name, for example:
Dim controls = Me.Controls.Find("btnColour1")
What you get back is an array of Controls. You get an array because Find can search all children (panels inside panels inside groupboxes inside forms etc) and it is thus conceivable that multiple controls in different panels will both have the same name. In your case if you know you only have one control called "btnColour1" it's safe to get it by array index:
Dim control = controls(0) 'controls variable is from the above Find
Lastly, remember that it comes back as a Control, the parent class for all controls. Because you know it's a button, it's safe to cast without check:
Dim button = DirectCast(control, Button)
Remember that if your property is available on the base Control class you don't even need a cast:
'here's a 1 line way to get the text of the button named btnColour1
'Find all controls named btnColour1, take the first, get the text
Dim t = Me.Controls.Find("btnColour1")(0).Text
If you want to refer to the buttons later in the program to change a setting without clicking the button, you can add each button to an array and call each of them with an index number:
Dim buttons(24) As Button
Then as the buttons are created, you can add each button to the array:
Dim bytCounter As Byte
For bytCounter = 1 To 25
Dim btnColour As New Button
Me.Controls.Add(btnColour)
buttons(bytCounter) = btnColour
you can then reference each button and their properties using the index number of the button in the array. You may also want to add a specific tag to each button to make each button more unique using:
btnColour.Tag = bytCounter

Behind-the-scenes VBA activity interfering with listboxes

Background:
I have a VBA project in an Excel spreadsheet. In it, I have a form that contains a frame that contains multiple labels/listboxes.
When the application is loaded, these listboxes are populated with data. (Nearly) everything works as expected, and this is what the form looks like:
My Problem:
My problem is that when a user clicks on an item in a listbox, that listbox is automatically "jumped into view" or something. For example; if I click on list item 5 like so, the frame scrolls down so that the listbox is at the top:
Before Click:
After Click:
You can see that the list item under my click has been selected, but the list was scrolled up beforehand so it's not actually the intended selection. This is not being done by any of my code.
If I put a "Stop" as the "Enter" and "Click" event handlers, the correct list item is selected and the list has not jumped at "Enter", but has by "Click".
More information:
If I continue to click on other elements from the same listbox, the listbox does not "jump". I can scroll up and down, and the listbox will not jump. As soon as I click in a DIFFERENT listbox (so "listbox1_Exit" and "listbox2_Enter" have been raised), the new listbox is "jumped" into view.
My Question:
My Question is: what "behind-the-scenes" code is VBA executing between these two events, and how can I prevent this from occuring? Or is there a way to "monitor" events?
(VBA appears to just resume execution if you "step" past the end of an event handler, rather than move to the next executing line of code - which would REALLY be helpful here...)
Edit:
Minimal example - plonk a frame on an empty form, add 2 listboxes to the frame and execute this code in the form:
Private Sub UserForm_Initialize()
Dim lb1 As Control
Dim lb2 As Control
Dim Frame1 As Control
Set Frame1 = Me.Controls("Frame1")
Set lb1 = Me.Controls("ListBox1")
Set lb2 = Me.Controls("ListBox2")
lb1.Height = 500
lb2.Height = 500
For i = 1 To 25
lb1.AddItem ("Potato " & i)
lb2.AddItem ("Frog " & i)
Next i
lb1.Top = 0
lb2.Top = lb1.Height + 10
Frame1.ScrollHeight = lb1.Height + lb2.Height + 10
End Sub
then scroll to the point where you can see the end of Listbox1 and the start of Listbox2, and try clicking elements in Listbox2.

Reversi VB.net logic behind it

I am trying to make the reversi game in VB.Net. I have some difficulties translating the game`s logic into vb.net
If a button is black and the button next to it is white,than the button next to the white one will be black wen pressed.
newButton.tag = colum of button + (row of button * amount of columns)
-> I made 64 buttons via a function loop and added a tag
Dim knop As Button = sender
Dim value As String = knop.Tag
If value = "...(?)" Then
knop.BackColor = Color.Black
If ....(?)
End If
End If
I already made a scheme with the label of the buttons, but I find it hard to implement the logic. Can someone help me out with thid one?
EDIT: http://i.stack.imgur.com/3gdrJ.png
If you use Dim ButtonList As List(Of List(Of Button)) and add the buttons to the form in runtime you can add each the button for each row to a list then add that list to ButtonList. Now you can access each button by the indexes in the 2 dimensional list.
Since you're changing the backcolor just use that instead of using the tag.

Creating a new instance of an existing control? (a bit more complicated than it sounds)

I know that if I want to dynamically create a new instance of an existing form, I can simply do this...
Dim NewForm As New ExistingForm
... and a new instance of all of the controls from ExistingForm will be available in NewForm.
But what if I want to create a new instance of an existing control that's inside a separate existing form?
More specifically, let's say I have 2 forms - FormA and FormB. Inside FormB is an existing panel (we'll call it ExistingPanel). And inside ExistingPanel are several buttons, text boxes, etc., arranged exactly how I want them.
OK, so... inside a button's click event in FormA, I want to do something like this (it doesn't work, obviously, but should give you a good idea as to what I'm trying to accomplish)...
Dim NewExistingPanel As New FormB.ExistingPanel
And then I want NewExistingPanel to contain new instances all of the individual controls from ExistingPanel (so that I can dynamically manipulate each one individually).
So basically, my program will need to create several NewExistingPanels at runtime. And I will need to access each one (and all of its child controls) individually, after they have been created.
How can I accomplish this? I've been experimenting with this for several hours with no luck so far, so figured I'd break down and ask the real professionals :)
When you create a new user control, you could use a dictionary with the tag value as key and the control name as value. Then you can access the control directly by using the IndexOfKey method.
Dim NewForm2 As New Form2
Dim ControlIndex As New Dictionary(Of String, String)
For I = 0 To 2
Dim NewPanel As New WindowsControlLibrary2.MyCustomPanel
NewPanel.Name = "Panel-" + I.ToString
NewPanel.Location = New Point(0 + (NewPanel.Size.Width * I), 0)
NewPanel.Tag = "MyTagValue" + I.ToString
ControlIndex.Add(NewPanel.Tag, NewPanel.Name)
NewForm2.Controls.Add(NewPanel)
NewForm2.Update()
Next
NewForm2.Show()
Dim CurrentPanel As WindowsControlLibrary2.MyCustomPanel =NewForm2.Controls(NewForm2.Controls.IndexOfKey(ControlIndex("MyTagValue1")))
To add control such as panel with textboxes ang button in it ..
In your project - Add > Usercontrol -->
in this part you can make panel with textboxes and button as you want
name it as "myPanel" and save it as "myPanel.vb" --> or whatever you want
In your form and the button named button1 you can add to your button1_click event :
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim mypanel1 As New MyPanel
mypanel1.Location = New Point(0, 0)
Controls.Add(mypanel1)
mypanel1.TextBox1.Text = "Hi, Im new"
End Sub
And you will get your panel at runtime ...
And you will get the textbox1.text fill with "Hi, I'm new" ...
You could create a user control that lays out your sub-controls the way you want them, then create new instances of that. Add New > User Control in the solution menu, then build, and your controls should be ready to drag into the designer at the top of the Toolbox or to instantiate in code like any other control.
To expand on my comment:
Private somePanels As New Dictionary(Of String, YourUserControl)
Then you can just add them as follows:
Dim c As New YourUserControl()
…
Me.Controls.Add(c)
somePanels.Add("SomeTag", c) ' Instead of using Tag; if your tags are numbers, use a List instead of a Dictionary
And access them as:
Dim c = somePanels("SomeTag")

Can I get a random button to blink in vb.net?

I'm creating a game where you have to click buttons in a certain sequence.
I want the buttons to blink in order at the beginning so the player could take a look at the sequence and memorize it..
on each round, the buttons get assigned new values, hence the order changes,
I want to be able to make any button blink, meaning instead of writing button1, I wanna be able to use button(i) (if it's possible)
thanks in advance!
You can put all your buttons that should blink into a list, then create a random number, and use this random number to get the button at this index.
Dim buttons = new Button() {button1, button2, button3} 'Put buttons into list
Dim r = new Random()
Dim seq_length = 3 'Let three buttons blink
For i = 0 To seq_length
Dim index = r.Next(0, buttons.Count()) 'Get random index
LetButtonBlink(buttons(index)) 'Use this index to select a button
Next