I was wondering if there is any way to refresh the cont numbers in a listbox
i am adding data with the code
ListBox1.Items.Add
I have set up as button to remove selected data with the code:
For i As Integer = ListBox1.SelectedIndices.Count - 1 To 0 Step -1
ListBox1.Items.RemoveAt(ListBox1.SelectedIndices.Item(i))
Next
say my list box is like this
Zach
Barry
John
Nick
Brodie
if i deleted say barry how can i make the numbers change so john would be 2. etc
The BindingList can be helpful here since it can listen for changes in the list.
For example, create a Person class and override the ToString function to show the rank and the name.
Public Class Person
Property Name As String
Property Rank As Integer
Public Overrides Function ToString() As String
Return Rank & ". " & Name
End Function
End Class
In your form, declare the list and add the event handler:
Private people As New BindingList(Of Person)
Public Sub New()
InitializeComponent()
AddHandler people.ListChanged, AddressOf people_ListChanged
people.Add(New Person() With {.Name = "Zach"})
people.Add(New Person() With {.Name = "Barry"})
people.Add(New Person() With {.Name = "John"})
people.Add(New Person() With {.Name = "Nick"})
people.Add(New Person() With {.Name = "Brodie"})
ListBox1.DataSource = people
End Sub
Private Sub people_ListChanged(sender As Object, e As ListChangedEventArgs)
For i As Integer = 0 To people.Count - 1
people(i).Rank = i + 1
Next
End Sub
The ListChanged event just updates the ranking of each member as they as slotted in the list, which will automatically update the ListBox since the DataSource is coming from the people list.
A simple delete button to test the list, and the rankings are automatically updated in the people list, which automatically updates the ListBox:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If ListBox1.SelectedIndex > -1 Then
people.Remove(ListBox1.SelectedItem)
End If
End Sub
If you have some idea of GDI+ drawing, a more interesting approach is to set your ListBox's DrawMode to OwnerDrawFixed mode and listen to ListBox's DrawItem event, something like this:
C#
private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
e.Graphics.DrawString((e.Index + 1).ToString() + ". " + listBox1.Items[e.Index].ToString(), listBox1.Font, Brushes.Black, e.Bounds);
}
VB.NET
Private Sub listBox1_DrawItem(sender As Object, e As DrawItemEventArgs)
e.DrawBackground()
e.Graphics.DrawString((e.Index + 1).ToString() & ". " & listBox1.Items(e.Index).ToString(), listBox1.Font, Brushes.Black, e.Bounds)
End Sub
Adding or removing any items to the ListBox will automatically renumber all the items.
You can use a List of string combined with the ListBox.
Dim NamesList1 As New List(Of String)
Private Sub Form_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
NamesList1.AddRange({"Zach", "Barry", "John", "Nick", "Brodie"})
FillListBoxItems()
End Sub
Private Sub FillListBoxItems()
ListBox1.Items.Clear()
For i As Integer = 0 To NamesList1.Count - 1
ListBox1.Items.Add(i + 1 & ". " & NamesList1.Item(i))
Next
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
For i As Integer = ListBox1.SelectedIndices.Count - 1 To 0 Step -1
NamesList1.RemoveAt(ListBox1.SelectedIndices.Item(i))
Next
FillListBoxItems()
End Sub
Related
the program is supposed to take the text in from the text boxes, combine it into a NewCustomer element, and then display it in a listbox. Below is the code i'm supposed to add to, i've tried lstCustomer.add(txtFirstname.text) but it turned to be an error. Thanks in advance for helping.
Public Class Form1
Private myCustomers As New ArrayList
Public ReadOnly Property SelectedCustomer As Customer
Get
Dim index As Integer = lstCustomer.SelectedIndex
If index <> -1 Then
Return lstCustomer.Items(index)
Else
Return Nothing
End If
End Get
End Property
Public Sub NewCustomer(ByVal fn As String, ByVal ln As String, ByVal a As Integer, ByVal e As String)
Dim temp As Customer
temp.FirstName = fn
temp.LastName = ln
temp.Age = a
temp.Email = e
myCustomers.Add(temp)
Me.lstCustomer.Items.Add(temp)
End Sub
Private Sub BtnTest_Click(sender As Object, e As EventArgs) Handles BtnTest.Click
NewCustomer("Homer", "Simpson", 40, "HSimpson#springf.com")
NewCustomer("Bruce", "Banner", 44, "green#giant.com")
End Sub
Public Sub displayCustomer(ByVal temp As Customer)
Me.TxtName.Text = temp.name
Me.TxtFirstName.Text = temp.FirstName
Me.TxtLastName.Text = temp.LastName
Me.TxtAge.Text = temp.Age
Me.TxtEmail.Text = temp.Email
End Sub
Private Sub BtnAdd_Click(sender As Object, e As EventArgs) Handles BtnAdd.Click
lstCustomer.add(TxtFirstName.Text And TxtLastName.Text And TxtEmail.Text And TxtAge.Text)
End Sub
I suggest using data binding, this makes it easier to work with the ListBox. First make sure to override ToString in the Customer class to make is displayable in the ListBox
Public Class Customer
Public Property FirstName As String
Public Property LastName As String
Public Property Age As Integer
Public Property Email As String
Public Overrides Function ToString() As String
Return $"{FirstName} {LastName} ({Age}) {Email}"
End Function
End Class
Then we use a List(Of Customer) instead of an ArrayList. The advantage is that the List(Of ) is strongly typed, i.e., its elements are of type Customer, where as the ArrayList has elements of type Object.
Also, we create a wrapper of type BindingList(Of Customer) to wrap our list to enable auto-updating of the ListBox. Example:
Public Class Form1
Dim customers As New List(Of Customer)
Dim customersBinding As BindingList(Of Customer)
Public Sub New()
InitializeComponent()
customersBinding = New BindingList(Of Customer)(customers)
lstCustomer.DataSource = customersBinding
End Sub
Private Sub NewCustomer(ByVal fn As String, ByVal ln As String, ByVal a As Integer, ByVal e As String)
Dim customer As New Customer With {
.FirstName = fn,
.LastName = ln,
.Age = a,
.Email = e
}
customersBinding.Add(customer)
lstCustomer.SelectedItem = customers(customers.Count - 1)
' or lstCustomer.SelectedIndex = customers.Count - 1
End Sub
Private Sub BtnTest_Click(sender As Object, e As EventArgs) Handles BtnTest.Click
NewCustomer("Homer", "Simpson", 40, "HSimpson#springf.com")
NewCustomer("Bruce", "Banner", 44, "green#giant.com")
End Sub
Public Sub DisplayCustomer(ByVal customer As Customer)
TxtFirstName.Text = customer.FirstName
TxtLastName.Text = customer.LastName
TxtAge.Text = customer.Age.ToString()
TxtEmail.Text = customer.Email
End Sub
Private Sub lstCustomer_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstCustomer.SelectedIndexChanged
Dim index As Integer = lstCustomer.SelectedIndex
If index >= 0 Then
DisplayCustomer(customers(index))
End If
End Sub
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
NewCustomer(TxtFirstName.Text, TxtLastName.Text, CInt(TxtAge.Text), TxtEmail.Text)
End Sub
End Class
In the constructor we create the binding list and set it as data source of the ListBox.
See how Sub NewCustomer only adds the new customer to the binding list. This inserts the customer to the wrapped list as well and at the same time updates the ListBox.
We also automatically select the last inserted customer in the ListBox with
lstCustomer.SelectedItem = customers(customers.Count - 1)
or (easier)
lstCustomer.SelectedIndex = customers.Count - 1
We use the SelectedIndexChanged event to automatically display the customer in the textboxes when the user selects another customer in the listbox.
You could also extend data binding to automatically bind the customer objects to the textboxes. You will find a lot of online tutorials on this subject.
I have a first form (form_notice_hashtag) called like this:
Public Sub afficher_hashtag(hashtag As String, plateforme_hashtag As String)
Dim form_notice_hashtag_1 As New form_notice_hashtag
form_notice_hashtag_1.StartPosition = FormStartPosition.CenterScreen
form_notice_hashtag_1.Show()
End Sub
In form_notice_hashtag_1, i have a button calling a 2nd form (form_recherche_thesaurus) like this:
Private Sub hashtag_thesaurus_search_button_Click(sender As Object, e As EventArgs) Handles hashtag_thesaurus_search_button.Click
Dim form_recherche_thesaurus_1 As New form_recherche_thesaurus With {
.StartPosition = FormStartPosition.Manual,
.Location = New Point(Me.Left + Me.Width, Me.Top)
}
form_recherche_thesaurus_1.ShowDialog(Me)
End Sub
In form_recherche_thesaurus, i have a datagridview listing some words. The user can select one word, then by clicking a button in form_recherche_thesaurus, the word which will be added to a textbox in form_notice_hashtag
Private Sub thesaurus_ok_button_Click(sender As Object, e As EventArgs) Handles thesaurus_ok_button.Click
Dim list_terms_array As String()
Select Case Owner.Name.ToString
Case "form_notice_hashtag"
list_terms_array = Split(Remove_Duplicates_From_Strings_With_SemiColon(form_notice_hashtag.hashtag_descripteurs_txtbox.Text & ";" & selected_term), ";")
form_notice_hashtag.hashtag_descripteurs_txtbox.Text = (String.Join(";", list_terms_array.Where(Function(s) Not String.IsNullOrEmpty(s))))
End Select
End Sub
I used a select because this mechanism would be used in the same way with other forms than form_notice_hashtag.
Problem: the textbox in form_notice_hashtag is not filled with the selected keywords. I guess it's because of the way form_notice_hashtag is called.
I can't use the solution as explained here Send values from one form to another form because i understood (maybe badly) that this solution works only if the 2nd form (form_recherche_thesaurus in my case) is closed (i.e closing was the trigger) which i don't want.
How can I proceed?
Thanks to jmcilhinney and this page of his blog, here is the solution that allows to transfer several data from a called form (form_recherche_thesaurus) to a calling form (form_notice_hashtag) without closing the called form .
Public Class form_notice_hashtag
Private WithEvents form_recherche_thesaurus_1 As form_recherche_thesaurus
Private selected_thesaurus_term As String
Private Sub form_recherche_thesaurus_1_TextBoxTextChanged(sender As Object, e As EventArgs) Handles form_recherche_thesaurus_1.TextBoxTextChanged
Dim list_terms_array As String() = Split(Remove_Duplicates_From_Strings_With_SemiColon(Me.hashtag_descripteurs_txtbox.Text & ";" & form_recherche_thesaurus_1.selected_term), ";")
Me.hashtag_descripteurs_txtbox.Text = (String.Join(";", list_terms_array.Where(Function(s) Not String.IsNullOrEmpty(s))))
End Sub
Private Sub hashtag_thesaurus_search_button_Click(sender As Object, e As EventArgs) Handles hashtag_thesaurus_search_button.Click
Dim form_recherche_thesaurus_1 As New form_recherche_thesaurus With {
.StartPosition = FormStartPosition.Manual,
.Location = New Point(Me.Left + Me.Width, Me.Top)
}
If Me.form_recherche_thesaurus_1 Is Nothing OrElse Me.form_recherche_thesaurus_1.IsDisposed Then
Me.form_recherche_thesaurus_1 = New form_recherche_thesaurus With {
.StartPosition = FormStartPosition.Manual,
.Location = New Point(Me.Left + Me.Width, Me.Top)
}
Me.form_recherche_thesaurus_1.Show()
End If
Me.form_recherche_thesaurus_1.Activate()
End Sub
End Class
Public Class form_recherche_thesaurus
Public Event TextBoxTextChanged As EventHandler
Private term_thesaurus As String
Public Property selected_term() As String
Get
Return term_thesaurus
End Get
Set(ByVal value As String)
term_thesaurus = value
End Set
End Property
Private Sub thesaurus_ok_button_Click(sender As Object, e As EventArgs) Handles thesaurus_ok_button.Click
Dim list_terms_array As String()
Me.selected_term = Me.thesaurus_search_results_datagrid.Item(0, Me.thesaurus_search_results_datagrid.CurrentRow.Index).Value
Me.DialogResult = DialogResult.OK
RaiseEvent TextBoxTextChanged(Me, EventArgs.Empty)
End Sub
I have 2 CheckedListBox that contains 3 strings each:
CheckedListBox1: "Apricot", "Banana", "Cherry"
CheckedListBox2: "Apple", "Blueberry", "Clementine"
I would like that everytime I click on my Button1, it checks if it contains the item, and if not it adds it to myList1 for CheckedListBox1, and myList2 for CheckedListBox2, but in the same order. I mean:
I check Apricot and Cherry, so myList1 is: "Apricot", "Cherry"
I uncheck them and check only Banana, so the list is: "Apricot", "Cherry", "Banana"
So I want the Apricot always being first, Banana second and Cherry third.
Same for myList2, obviously.
My actual code is:
Dim myList1 As New List(Of String)
Dim myList2 As New List(Of String)
Dim myFullList As New List(Of String)
Private Sub Submit() Handles Button1.Click
For Each item In CheckedListBox1.CheckedItems
If Not myList1.Contains(item) Then
myList1.Add(item)
End If
Next
For Each item In CheckedListBox2.CheckedItems
If Not myList2.Contains(item) Then
myList2.Add(item)
End If
Next
myFullList.Add(String.Join(", ", myList1)
myFullList.Add(String.Join(", ", myList2)
End Sub
Thanks in advance, guys ! :)
You might consider doing things a bit differently. Define a custom type and bind a list of that type to the CheckedListBox. When an item is checked, set a flag in that item. You can then just get the items from that list that have that flag set.
Public Class CheckListItem
Public Property Text As String
Public Property Checked As Boolean
Public Overrides Function ToString() As String
Return Text
End Function
End Class
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim items = {New CheckListItem With {.Text = "Apricot"},
New CheckListItem With {.Text = "Banana"},
New CheckListItem With {.Text = "Cherry"}}
CheckedListBox1.DataSource = items
End Sub
Private Sub CheckedListBox1_ItemCheck(sender As Object, e As ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
If e.NewValue = CheckState.Checked Then
DirectCast(CheckedListBox1.Items(e.Index), CheckListItem).Checked = True
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim checkedItems = CheckedListBox1.Items.Cast(Of CheckListItem)().Where(Function(cli) cli.Checked)
MessageBox.Show(String.Join(", ", checkedItems))
End Sub
enter image description here <<< my interface
I am working on something for my exam next week.
I must use Visual Basic. I am supposed to create an array with an integer and string. Integer = distance String = name. there will be 2 textboxes, 2 labels and 2 buttons.
txtname.text, txtdistance.text, lblname, lbldistance, btninputdata and btnshowcontent
btninputdata should be disabled after filling the 30 arrays and making btnshowcontent to be visible and show all the 30 values (inserted values via textboxes) in lblname and lbldistance.
Whereas they both need to be inserted via a textbox store into the array and then using a btnshowcontent the stored array should be displayed on separate labels of name and distance.
My codes:
Public Class Form1
Dim ara(29) As String
Private Sub Form1_Load(sender As Object, e As EventArgs)
End Sub
Private Sub btninputdata_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btninputdata.Click
If txtname.Text <> "" Then
For h As Integer = 0 To 29
If ara(h) = "" Then
ara(h) = txtname.Text
txtname.Clear()
Exit Sub
End If
Label1.Text = ara.ToString()
Next
MsgBox("arry full")
btninputdata.Visible = False
btnshowcontent.Visible = True
End If
End Sub
Private Sub btnshowcontent_Click(sender As Object, e As EventArgs) Handles btnshowcontent.Click
'ListBox1.Items.Clear()
'ListBox1.Items.AddRange(ara)
''Label1.Text &= ara(I) & ""
End Sub
Private Sub Form1_Load_1(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
End Class
You'll want to start with something like this. Not sure how you're really trying to display everything, though. You'd probably want to do validation on the distance field also.
Public Class Form1
Dim Ara As New List(Of MyGroup)
Private Sub btninputdata_Click(sender As Object, e As EventArgs) Handles btninputdata.Click
If txtName.Text.Trim() <> String.Empty Then
Ara.Add(New MyGroup With {.Name = txtName.Text, .Distance = txtDistance.Text})
If Ara.Count >= 30 Then
'Show/Hide buttons
End If
End If
End Sub
End Class
Public Class MyGroup
Public Name As String
Public Distance As Decimal
End Class
If you truly must use an array you can do something like this:
Public Class Form1
Private Ara(29) As MyGroup
Private Sub btninputdata_Click(sender As Object, e As EventArgs) Handles btninputdata.Click
If txtName.Text.Trim() <> String.Empty Then
Dim EmptyLocation = Array.FindIndex(Ara, Function(x) x Is Nothing)
If EmptyLocation > -1 Then
Ara(EmptyLocation) = New MyGroup With {.Name = txtName.Text, .Distance = txtDistance.Text}
Return
End If
'Show/Hide buttons
'Display the results however.
End If
End Sub
End Class
Public Class MyGroup
Public Name As String
Public Distance As Decimal
End Class
First of all excuse me for my poor grammar and vocabulary :)
please see this source and run it:
Public Class Form1
Public pointX As Integer
Public pointY As Integer = 32
Public dynamicText As TextBox
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
pointX = 330
For i = 1 To 4
dynamicText = New Windows.Forms.TextBox
dynamicText.Name = "T" + Trim(Str(i))
dynamicText.Text = ""
dynamicText.Location = New Point(pointX, pointY)
dynamicText.Size = New Size(100, 20)
Me.Controls.Add(dynamicText)
pointX = pointX - 106
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
pointX = 330
pointY = pointY + 26
For i = 1 To 4
dynamicText = New Windows.Forms.TextBox
dynamicText.Name = "T" + Trim(Str(i))
dynamicText.Text = ""
dynamicText.Location = New Point(pointX, pointY)
dynamicText.Size = New Size(100, 20)
Me.Controls.Add(dynamicText)
pointX = pointX - 106
AddHandler dynamicText.Click, AddressOf printHello1
Next
End Sub
Private Sub printHello1(ByVal sender As System.Object, ByVal e As System.EventArgs)
MsgBox(dynamicText.Name)
If dynamicText.Name = "T1" Then MsgBox("Oh! this is T1")
End Sub
End Class
why If never is not true?!
why MsgBox(dynamicText.Name) always return T4?!
i want all controlls to be access by name or array of names.
please help me thank you. :)
The global variable dynamicText takes the value of the last TextBox added in the loop inside the Button1_Click event. This happens to be the control named T4. You don't really need a global variable in this case. You can cast the sender parameter to a TextBox instance because the sender parameter is the control that has raised the event.
Private Sub printHello1(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim txt = CType(sender, "TextBox")
if txt IsNot Nothing then
MsgBox(txt.Name)
If txt.Name = "T1" Then MsgBox("Oh! this is T1")
End If
End Sub
You also don't need to recreate the controls again in the button click event. The action executed in the form load event is enough (You could add the AddHandler there). Global variables are dangerous, avoid them when possible.
See if this is acceptable. Place a panel at the bottom of your form, set Dock to Bottom, add a single button to the panel and a TextBox. Place a FlowLayoutPanel onto the form, Dock = Fill, AutoScroll = True.
The code below creates the amount of TextBox controls as inputted into TextBox. Each newly created TextBox a click event is added with simple logic.
Form code
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim count As Integer = 0
If Integer.TryParse(TextBox1.Text, count) Then
Dim demo = New TextBoxCreate(FlowLayoutPanel1, "Demos", count)
demo.CreateTextBoxes()
End If
End Sub
End Class
Class code (add a new class to the project, name it TextBoxCreate.vb)
Public Class TextBoxCreate
Public Property TextBoxes As TextBox()
Public Property TextBoxBaseName As String
Public Property TextBoxCount As Integer
Public Property ParentControl As Control
Public Sub New(
ByVal ParentControl As Control,
ByVal BaseName As String,
ByVal Count As Integer)
Me.ParentControl = ParentControl
Me.TextBoxBaseName = BaseName
Me.TextBoxCount = Count
End Sub
Public Sub CreateTextBoxes()
Dim Base As Integer = 10
TextBoxes = Enumerable.Range(0, TextBoxCount).Select(
Function(Indexer)
Dim b As New TextBox With
{
.Name = String.Concat(TextBoxBaseName, Indexer + 1),
.Text = (Indexer + 1).ToString,
.Width = 150,
.Location = New Point(25, Base),
.Parent = Me.ParentControl,
.Visible = True
}
AddHandler b.Click, Sub(sender As Object, e As EventArgs)
Dim tb As TextBox = CType(sender, TextBox)
If tb.Name = TextBoxBaseName & "1" Then
tb.Text = "Got it"
Else
MessageBox.Show(tb.Name)
End If
End Sub
Me.ParentControl.Controls.Add(b)
Base += 30
Return b
End Function).ToArray
End Sub
End Class