Add click events to ToolStripTextBox in VB.NET when created in code - vb.net

I am creating tabs to keep track of open files. When I create them I can set their properties and add them to the list in a MenuStrip.
Before I do so I want to add a click event function. Since this is in a function and will be run multiple times, I need to have a dynamic way to do add these event handlers. I cannot write this:
Private Sub ToolStripTextBox1_Click(sender As Object, e As EventArgs) Handles ToolStripTextBox1.Click
' ...
End Sub
If I do this I can only name them all one name. I want to be able to add a click event that applies to them separately as individual items.
UPDATE:
Dim textFile As ToolStripTextBox = New ToolStripTextBox("textFile")
FileList.Items.Add(textFile)
textFile.Text = filename
textFile.ReadOnly = True
textFile.BackColor = Color.FromArgb(61, 61, 61)
textFile.ForeColor = Color.White
This is the creation and personalization code. Though when you guys suggested AddButton_Click() Handles AddButton.Click It doesn't work because AddButton isn't an actual button

You can keep track of the items, add add and remove click handlers with the following code
Private FileList As New List(Of ToolStripItem)()
' put this code where you add an item
Dim filename = "whatever"
Dim textFile As ToolStripTextBox = New ToolStripTextBox(filename)
textFile.Text = filename
textFile.ReadOnly = True
textFile.BackColor = Color.FromArgb(61, 61, 61)
textFile.ForeColor = Color.White
add(textFile)
Private Sub clickHandler(sender As Object, e As EventArgs)
Dim item = DirectCast(sender, ToolStripItem)
MessageBox.Show(item.Text)
End Sub
Private Sub add(textFile As ToolStripItem)
FileList.Add(textFile) ' Since I don't know what FileList is, I ued List
AddHandler textFile.Click, AddressOf clickHandler
OpenProjectToolStripMenuItem.DropDownItems.Add(textFile) ' add to whatever menu item you normally do
End Sub
Private Sub remove(textFile As ToolStripItem)
FileList.Remove(textFile)
RemoveHandler textFile.Click, AddressOf clickHandler
OpenProjectToolStripMenuItem.DropDownItems.Remove(textFile)
End Sub

The sample click event in your code includes this:
sender As Object
You can re-use this one event handler, because whichever menu item is clicked will be the sender. So you do something like this:
Private Sub ToolStripTextBox1_Click(sender As Object, e As EventArgs) Handles ToolStripTextBox1.Click
Dim menuItem = DirectCast(sender, ToolStripMenuItem)
If menuItem Is Nothing Then Return
'If you need to choose different code for each item:
Select Case menuItem.name
Case "some item"
Case "some other item"
End Select
End Sub
And you can connect your dynamic toolstrip items to this method using AddHandler:
AddHandler myMenuStrip.Click, AddressOf ToolSTripTextBox1_Click

Related

Index Selection in ListView created at runtime in Visual Basic (Visual Studio 2019)

I am trying to use a ListView box created at runtime and I am able to populate items but the SelectedIndexChanged event is not working. I know I am missing something really simple. Below is a minimal working example where I am creating the ListView on a button click and populating with a couple of items. When I select an item nothing happens in the SelectedIndexChanged event.
Public Class Form1
Dim lstMylist As ListView
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
lstMylist = New ListView()
lstMylist.Location = New Point(37, 312)
lstMylist.Size = New Size(150, 150)
Me.Controls.Add(lstMylist)
lstMylist.View = View.SmallIcon
Dim myListItem1 As ListViewItem
myListItem1 = lstMylist.Items.Add("Item 1")
Dim myListItem2 As ListViewItem
myListItem2 = lstMylist.Items.Add("Item 2")
End Sub
Private Sub lstMylist_SelectedIndexChanged(sender As Object, e As EventArgs)
MessageBox.Show("I am here")
Select Case lstMylist.FocusedItem.Index
Case 0
MessageBox.Show("item 1")
Case 1
MessageBox.Show("item 2")
Case Else
MessageBox.Show("invalid")
End Select
End Sub
End Class
You need to add the event handler to the ListView SelectedIndexChanged event
lstMylist = New ListView()
lstMylist.Location = New Point(37, 312)
lstMylist.Size = New Size(150, 150)
' Add the event handler for the listview
AddHandler lstMyList.SelectedIndexChanged, AddressOf lstMylist_SelectedIndexChanged
Me.Controls.Add(lstMylist)
lstMylist.View = View.SmallIcon
As outlined by djv it is important to call RemoveHandler if you remove the ListView
RemoveHandler lstMyList.SelectedIndexChanged, AddressOf lstMylist_SelectedIndexChanged
Steve's answer will work. But an alternative is to simply make your ListView WithEvents
Dim WithEvents lstMylist As ListView
and add Handles to the method declaration
Private Sub lstMylist_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstMylist.SelectedIndexChanged
This is more a VB.NET way of doing things. AddHandler is similar to C# Event += new EventHandler syntax.
Note, if using AddHandler, a matching RemoveHandler should appear if the ListView is to be removed and added repeatedly.

How to degrade similar tool strip button procedures to a single in VB.NET

I'm using ToolStrip and it's buttons to change GUI structure with an example code how i change GUIs with tool strip buttons. Are there any methods to use them more easy way like when clicked event of ToolStripButton handled it can call a single procedure etc.? In current case it seems i'm coding in a bad way.
For example if user click the Home button it highlights the button as selected and hides other panel elements and make visible Home's panel.
Private Sub tsbHome_Click(sender As Object, e As EventArgs) Handles tsbHome.Click
tsbHome.Checked = True
tsbTools.Checked = False
tsbReport.Checked = False
tsbAnalyze.Checked = False
'... Tool Strip Button lists continues...
pnlHome.Visible = True
pnlTools.Visible = False
pnlReport.Visible = False
pnlAnalyze.Visible = False
' ... Panel lists continues...
End Sub
if user click the Tools button it highlights the button as selected and hides other panel elements and make visible Tool's panel.
Private Sub tsbTools_Click(sender As Object, e As EventArgs) Handles tsbTools.Click
tsbHome.Checked = False
tsbTools.Checked = True
tsbReport.Checked = False
tsbAnalyze.Checked = False
'... Tool Strip Button lists continues...
pnlHome.Visible = False
pnlTools.Visible = True
pnlReport.Visible = False
pnlAnalyze.Visible = False
' ... Panel lists continues...
End Sub
There are two tricks to making this code much simpler. The first is knowing you can have more than one item in the Handles clause of an event method declaration. (You can also omit that clause, and use AddHandler to set up event handlers for a lot of controls to one method.) The other trick is knowing how to use the sender argument to determine which of the several controls connected to this method was used.
Put those together, and you get one method that will work to change to any of your views.
Private Sub NavigationMenuItem_Click(sender As Object, e As EventArgs) Handles tsbHome.Click, tsbTools.Click, tsbReport.Click, tsbAnalyzer.Click
'First Suspend Layout, to avoid extra screen re-draws
Me.SuspendLayout()
'Set your checkboxes
tsbHome.Checked = sender Is tsbHome
tsbTools.Checked = sender Is tsbTools
tsbReport.Checked = sender Is tsbReport
tsbAnalyze.Checked = sender Is tsbAnalyze
'Then De-select EVERYTHING
pnlHome.Visible = sender Is tsbHome
pnlTools.Visible = sender Is tsbTools
pnlReport.Visible = sender Is tsbReport
pnlAnalyze.Visible = sender Is tsbAnalyze
' ... lists continues...
'Finally, resume layout so all changes draw to the screen at once
Me.ResumeLayout()
End Sub
We can make this simpler if you add code to the Form Load or InitializeComponent() method to put the panels and toolstrip buttons into lists:
Private ViewButtons As List(Of ToolStripButton)
Private ViewPanels As List(Of Panel)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ViewButtons = New List(Of ToolStripButton) From {tsbHome, tsbTools, tsbReport, tsbAnalyze}
ViewPanels = New List(Of Panel) From {pnlHome, pnlTools, pnlReport, pnlAnalyze}
For Each b In ViewButtons
AddHandler b.Click, AddressOf NavigationMenuItem_Click
Next
End Sub
Private Sub NavigationMenuItem_Click(sender As Object, e As EventArgs)
Me.SuspendLayout()
For i As Integer = 0 To ViewButtons.Length - 1
Dim selected As Boolean = ViewButtons(i) Is sender
ViewButtons(i).Checked = selected
ViewPanels(i).Visible = selected
Next
Me.ResumeLayout()
End Sub

VB: adding object to a tabcontrol tab which doiesnt exist at this time

i want to add a tabcontrol tab by pressing on a button:
Dim inp As String
inp = TextBox6.Text
TabControl2.TabPages.Add(inp)
and when i open this tabpage some object should be already created like a button and a textbox, etc.
i havent found any type of onload events for a tabpage so i tried to add this with:
TabPage8.Controls.Add(New Button())
tabpage8 would be the name of the new created tabpage but like vb already told me, i cant add objects to a tabpage which doesnt exist at that time.
is there any way i can do that or have you any other ideas which could help me?
Your code is close. Try the following:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TabControl2.TabPages.Add("Test")
Dim tp = TabControl2.TabPages(TabControl2.TabPages.Count - 1)
Dim b = New Button()
b.Text = "My Button"
tp.Controls.Add(b)
AddHandler b.Click, AddressOf MyButton_Click
End Sub
Private Sub MyButton_Click(sender As Object, e As EventArgs)
MessageBox.Show("MyButton clicked")
End Sub
This code grabs the last page added and adds a button to it. It also configures the button as needed and adds an event handler.

Button Array - how to pass a parameter to shared handler

I have a bit of code where i have a dynamically created array or buttons with staff pictures on them, as well as the staff's name. I've added one handler to handle any button click from any of the buttons. where i am stuck is, if you look at the code below, it all works fine, and if you click any of the buttons you get the "aha" test message. but i want the name of the staff clicked on (so btnArray(i).Text) to be passed to the handler for further processing. I tried adding a ByVal parameter to the handler but that caused an error. what's the correct way to do this? As i said, the code below works for me, i just am at a loss as to how to add the extra functionality.
Dim btnArray(staffcount) As System.Windows.Forms.Button
For i As Integer = 1 To staffcount - 1
btnArray(i) = New System.Windows.Forms.Button
btnArray(i).Visible = True
btnArray(i).Width = 80
btnArray(i).Height = 101
btnArray(i).BackgroundImage = Image.FromFile(picloc(i))
btnArray(i).BackgroundImageLayout = ImageLayout.Stretch
btnArray(i).Text = staffname(i)
Dim who As String
who = btnArray(i).Text
AddHandler btnArray(i).Click, AddressOf Me.theButton_Click
btnArray(i).ForeColor = Color.White
btnArray(i).TextAlign = ContentAlignment.BottomCenter
Dim fnt As Font
fnt = btnArray(i).Font
btnArray(i).Font = New Font(fnt.Name, 10, FontStyle.Bold)
FlowLayoutPanel1.Controls.Add(btnArray(i))
Next i
End Sub
Private Sub theButton_Click()
MsgBox("aha")
End Sub
First, correct the signature of your shared handler.
Private Sub theButton_Click(sender As Object, e As EventArgs)
End Sub
Once that is done getting the text of the button clicked is a simple matter.
Private Sub theButton_Click(sender As Object, e As EventArgs)
Dim textOfButtonClicked As String = DirectCast(sender, Button).Text
MessageBox.Show(textOfButtonClicked)
End Sub
The sender is the button that was clicked. Since signatures use objects for the sender the DirectCast 'changes' it to button and you then can access the .Text property of the button.
If there are more manipulations you want to perform on the clicked button you could do it this way
Private Sub theButton_Click(sender As Object, e As EventArgs)
Dim whBtn As Button = DirectCast(sender, Button) ' get reference to button clicked
Dim textOfButtonClicked As String = whBtn.Text
MessageBox.Show(textOfButtonClicked)
'e.g. change the color
whBtn.BackColor = Color.LightYellow
End Sub

SelectionChanged event occurs more times than it should

I have grid and those grid is populate on Form's load event. At the end line of that event i am hooking method handler for my SelectionChanged event of this grid. I want to get current selected row's zero cell's 1 value. Unfortunately when i run program my SelectionChanged event method handler is called infinite times... And i have no idea why is that.
So its basically like this:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
some code which populating data to grid...
'here hooking up method after data is there already to not fire it up during grid population
AddHandler gridArtikels.SelectionChanged, AddressOf gridArtikels_SelectionChanged
End Sub
and this is event handler method itself:
Private Sub gridArtikels_SelectionChanged(sender As Object, e As GridEventArgs)
RemoveHandler gridArtikels.SelectionChanged, AddressOf gridArtikels_SelectionChanged
If gridArtikels.PrimaryGrid.Rows.Count > 0 Then
gridArtikels.PrimaryGrid.SetSelectedRows(0, 1, True)
ItemPanelImgs.Items.Clear()
'Dim images As New List(Of Article_Image)
Dim selectedNummer As String = String.Empty
selectedNummer = gridArtikels.PrimaryGrid.SelectedRows(0).Cells(1).Value.ToString()
'images = ArtikelsAndTheirVariationsFinal.GetImagesForArticle(selectedNummer)
'ItemPanelImgs.DataSource = images
End If
AddHandler gridArtikels.SelectionChanged, AddressOf gridArtikels_SelectionChanged
End Sub
P.S I am using to be concrete supergrid control from DotnetBar devcomponenets but it shouldn't be diffrent from ordinary controls behaviour.
What could be wrong here?
For those whom would like to debug here is sample app
EDIT:
I also tried this way but its still going to infinitive loop...
Public IgnoreSelectionChanged As Boolean = False
Private Sub gridArtikels_SelectionChanged(sender As Object, e As GridEventArgs) Handles gridArtikels.SelectionChanged
If IgnoreSelectionChanged Then Exit Sub
IgnoreSelectionChanged = True
If gridArtikels.PrimaryGrid.Rows.Count > 0 Then
gridArtikels.PrimaryGrid.SetSelectedRows(0, 1, True)
ItemPanelImgs.Items.Clear()
'Dim images As New List(Of Article_Image)
Dim selectedNummer As String = String.Empty
selectedNummer = gridArtikels.PrimaryGrid.SelectedRows(0).Cells(1).Value.ToString()
'images = ArtikelsAndTheirVariationsFinal.GetImagesForArticle(selectedNummer)
'ItemPanelImgs.DataSource = images
End If
IgnoreSelectionChanged = False
End Sub