Adding Selected Item in a Listbox to a Label in Visual Basic - vb.net

In the program I'm writing I'm stuck on one of the last steps which is to display an employee's name and salary selected from a listbox in labels (one for the name and one for the salary), but I cannot figure out how to do this. The employee's names and salaries are read in from a file and are placed in the corresponding listboxes on 3 different forms (two that only list names, and one that only lists salaries). On the last form, the user is supposed to select the name of one of the employees and that person's name is supposed to appear in one label (lblName) and their salary is supposed to appear in another label (lblSalary). The names are listed in the selectable listbox, but when I click on one of them nothing happens.
Here is the code I have so far on the main form:
Option Strict On
Imports System.IO
Public Class Main
Private Sub open_Click(sender As Object, e As EventArgs) Handles open.Click
Dim open As New OpenFileDialog
open.Filter = "text files |*.txt|All Files|*.*"
open.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
If open.ShowDialog() = Windows.Forms.DialogResult.OK Then
Dim selectedFileName As String = System.IO.Path.GetFileName(open.FileName)
showNames.Enabled = True
showSalaries.Enabled = True
showEmployee.Enabled = True
End If
Dim container As New List(Of Project9)
Using reader As New StreamReader(open.OpenFile)
While Not reader.EndOfStream
Dim employee As New Project9
employee.Name = reader.ReadLine()
employee.Salary = CDbl(reader.ReadLine())
container.Add(employee)
End While
End Using
For Each item As Project9 In container
Names.lstNames.Items.Add(item.Name)
frmTotal.lstShow.Items.Add(item.Name)
Salaries.lstSalaries.Items.Add(item.Salary)
Next
End Sub
Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ExitToolStripMenuItem.Click
Me.Close()
Names.Close()
Salaries.Close()
frmTotal.Close()
End Sub
Private Sub showNames_Click(sender As Object, e As EventArgs) Handles showNames.Click
Names.Show()
End Sub
Private Sub showSalaries_Click(sender As Object, e As EventArgs) Handles showSalaries.Click
Salaries.Show()
End Sub
Private Sub showEmployee_Click(sender As Object, e As EventArgs) Handles showEmployee.Click
frmTotal.Show()
End Sub
End Class
Public Class Project9
Dim strName As String
Dim dblSalary As Double
Public Property Name As String
Get
Return strName
End Get
Set(value As String)
strName = value
End Set
End Property
Public Property Salary As Double
Get
Return dblSalary
End Get
Set(value As Double)
If dblSalary < 0 Then
dblSalary = 10
End If
dblSalary = value
End Set
End Property
Public Function computeSalary(intMonths As Integer) As Double
Dim dblTotal As Double = dblSalary * intMonths
Return dblTotal
End Function
End Class
And here's the code from the 4th form which is the one displaying the selected item in labels:
Public Class frmTotal
Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnCalculate.Click
lblName.Text = lstShow.SelectedItem(Name)
Dim intMonths As Integer
intMonths = InputBox("How many months would you like to calculate this employee's salary for?")
End Sub
End Class
Also, how would I be able to make a button visible only after an item has been selected?
Any help would be greatly appreciated.

If you leverage the Datasource property of the listbox you can actually fill the listbox with Project9 items and use the DisplayMember property to choose which property you display in the listbox. This has several advantages. Whenever a listbox item is selected it can be cast as an object of type Project9 and you can display whichever properties you want to the labels. Also the selection is tied together across the listboxes so that a selection in one is the same selection in the others. Here's an example of how that might look:
Dim employees As New List(Of Project9)(
{
New Project9 With {.Name = "A", .Salary = 1000},
New Project9 With {.Name = "B", .Salary = 1200},
New Project9 With {.Name = "C", .Salary = 1100}
})
ListBox1.DataSource = employees
ListBox1.DisplayMember = "Name"
ListBox2.DataSource = employees
ListBox2.DisplayMember = "Salary"
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
Dim selectedemployee = DirectCast(ListBox1.SelectedItem, Project9)
Label1.Text = selectedemployee.Name
Label2.Text = selectedemployee.Salary.ToString
End Sub

Related

Issue with item order in List and CheckedListBox

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

Add array values from textboxes and display in a label

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

Datagridview drag&drop rows when using datasource

I'm trying to get my first application up and running, but i'm struggling with drag and drop operations in the datagridview control.
I have created a datagrid view that has a datasource connected to it.
Public oBodyAssembly As New BindingList(Of BodyComponent)
DataGridView1.DataSource = oBodyAssembly
In this DataSource the users creates new objects and these are displayed in the datagridview. To allow the user to correct or alter his initial order of adding objects I would like to have them drag and drop rows to rearrange the position of the objects in the grid and also in the DataSource.
I have tried this example code I have found written in C# and altered it to VB.NET, it works in the fact that I can determinate the row I drag and determinate the position of the drop.
Link to the example code
But then the code in the sample inserts a new row and removes the old. This doesn't work for me. The removing works fine, and the object is also deleted from my DataSource. The inserting of the new row on the other hand doesn't.
My datasource is a BindingList(Of BodyComponent) It only contains object that are derived from the BodyComponent class.
How can I get this operation to work? I'm stuck..
Here is the code I have so far for the drag and drop operation.
Public oRowIndexMouseDown As Integer
Public oRow As DataGridViewRow
Private Sub BodyAssemblyDrag_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles DataGridView1.MouseDown
If DataGridView1.SelectedRows.Count = 1 Then
If e.Button = MouseButtons.Left Then
oRow = DataGridView1.SelectedRows(0)
oRowIndexMouseDown = DataGridView1.SelectedRows(0).Index
'Debug.Print("Row to move = " & oRowIndexMouseDown)
DataGridView1.DoDragDrop(sender, DragDropEffects.Move)
End If
End If
End Sub
Private Sub BodyAssemblyDrag_dragenter(ByVal sender As Object, ByVal e As DragEventArgs) Handles DataGridView1.DragEnter
If DataGridView1.SelectedRows.Count = 1 Then
e.Effect = DragDropEffects.Move
End If
End Sub
Private Sub BodyAssemblyDrag_dragdrop(ByVal sender As Object, ByVal e As DragEventArgs) Handles DataGridView1.DragDrop
Dim oPoint As Point
oPoint = DataGridView1.PointToClient(New Point(e.X, e.Y))
Dim oRowIndexMouseDrop As Integer
oRowIndexMouseDrop = DataGridView1.HitTest(oPoint.X, oPoint.Y).RowIndex
'Debug.Print("Drop row # " & oRowIndexMouseDrop)
If Not oRowIndexMouseDrop = oRowIndexMouseDown Then
'DataGridView1.Rows.RemoveAt(oRowIndexMouseDown)
'DataGridView1.Rows.Insert(oRowIndexMouseDrop, oRow)
End If
End Sub
Screenshot of winform
Add: method of creating objects in the list.
Public oBodyAssembly As New List(Of BodyComponent)
Private Sub BTN_BODY_ADD_CILINDER_Click(sender As Object, e As EventArgs) Handles BTN_BODY_ADD_CILINDER.Click
' Create a new cylinder and add it into the oBodyAssembly
Dim oCylinder As New Body_Cylinder
oBodyAssembly.Add(oCylinder)
' Set the index number for this cylinder
oCylinder.Index = oBodyAssembly.Count
' Set the component type
oCylinder.Type = BodyComponent.BodyComponentType.Cylinder
End Sub
Private Sub BTN_BODY_ADD_CONE_Click(sender As Object, e As EventArgs) Handles BTN_BODY_ADD_CONE.Click
' Create a new cone and add it into the oBodyAssembly
Dim oCone As New Body_Cone
oBodyAssembly.Add(oCone)
' Set the index number for this cylinder
oCone.Index = oBodyAssembly.Count
' Set the component type
oCone.Type = BodyComponent.BodyComponentType.Cone_reduction
End Sub
Classes:
Public Class BodyComponent
' Basic properties that are required for all of the bodycompenents
' regardless of the type.
Public Property Index() As Double
Public Property Type() As BodyComponentType
Public Property Height() As Double
Public Property Thickness() As Double
Public Property Elevation() As Double
Private Property Mass() As Double
' Type Enum that defines what kind of body component is created.
Public Enum BodyComponentType
Cylinder = 0001
Cone_reduction = 0002
End Enum End Class
Derived object ( same for cone )
Public Class Body_Cylinder
' Get the base properties
Inherits BodyComponent
' Set new properties that are only required for cylinders
Public Property Segments() As Integer
Public Property LW_Orientation() As Double End Class
First, since a BindingList cannot be sorted or ordered (without recreating the whole collection), I would use a simple List(Of T) with a BindingSource:
' Form level declarations:
Private Animals As List(Of AnimalEx)
Private BSAnimal As BindingSource
Then, once the list is created:
Animals = New List(Of AnimalEx)
' add Animals aka BodyComponent objects, then...
BSAnimal = New BindingSource(Animals, Nothing)
dgv.DataSource = BSAnimal
You will have to learn some new methods to manage the data. Since now, the List holds the data but the BindingSource provides the binding capabilities, some things you do to the List and some thru the BindingSource.
As for the row drag-drop, the code in this answer is a nice starting point, but there are a few things lacking. It doesnt account for a) A bound DGV, b) Users trying to drag the NewRow, c) users clicking on Non-Row areas of the DGV (empty/open portions) d) Allow the mouse to do other things like resize columns. I fixed those, but there may be other mouse ops to exempt.
' Form-level declarations
Private fromIndex As Integer = -1
Private bMouseDn As Boolean = False
Private MouseDnPt As Point = Point.Empty
Private Sub dgv_DragOver(sender As Object, e As DragEventArgs) Handles dgv.DragOver
e.Effect = DragDropEffects.Move
End Sub
Private Sub dgv_MouseDown(sender As Object, e As MouseEventArgs) Handles dgv.MouseDown
bMouseDn = (e.Button = Windows.Forms.MouseButtons.Left)
End Sub
Private Sub dgv_MouseMove(sender As Object, e As MouseEventArgs) Handles dgv.MouseMove
If bMouseDn Then
' first time, just grab the start location
If (MouseDnPt = Point.Empty) Then
MouseDnPt = e.Location
Exit Sub
End If
End If
If bMouseDn AndAlso MouseDnPt <> Point.Empty Then
Dim hitTst = dgv.HitTest(e.X, e.Y)
If hitTst IsNot Nothing AndAlso fromIndex = -1 AndAlso hitTst.RowIndex > -1 Then
fromIndex = hitTst.RowIndex
If dgv.Rows(fromIndex).IsNewRow = False Then
dgv.DoDragDrop(dgv.Rows(fromIndex), DragDropEffects.Move)
End If
End If
End If
End Sub
Private Sub dgv_MouseUp(sender As Object, e As MouseEventArgs) Handles dgvDD.MouseUp
If bMouseDn AndAlso (e.Button = Windows.Forms.MouseButtons.Left) Then
bMouseDn = False
End If
End Sub
I used a simple Point in place of the Rectangle, it tests for non-row area clicks and only begins to drag when the mouse moves and has the left button down. It also declines to DragDrop the NewRow.
Like the original version, it is dragging a DataGridViewRow. But since we want (must) change the DataSource, not the DGV rows, we have to get the item back from the DataSource:
Private Sub dgv_DragDrop(sender As Object, e As DragEventArgs) Handles dgv.DragDrop
Dim p As Point = dgv.PointToClient(New Point(e.X, e.Y))
Dim dragIndex = dgv.HitTest(p.X, p.Y).RowIndex
If (e.Effect = DragDropEffects.Move) Then
' cast to a row
Dim dragRow As DataGridViewRow = CType(e.Data.GetData(GetType(DataGridViewRow)),
DataGridViewRow)
' get related Animal object
Dim a As AnimalEx = CType(dragRow.DataBoundItem, AnimalEx)
' manipulate DataSource:
BSAnimal.RemoveAt(fromIndex)
BSAnimal.Insert(dragIndex, a)
' if the DGV is SingleSelect, you may want:
'dgv.Rows(dragIndex).Selected = True
' we are done dragging
bMouseDn = False
fromIndex = -1
MouseDnPt = Point.Empty
End If
End Sub
Result:
The "non row" area mentioned is the yellowish areas.

Pass variable to new form with Datatable and Listbox

I am currently trying to write an application like address book. Listbox works properly, it shows everything corretly. But I need to pass id of chosen listbox item to another form. I got code like this in Form2:
Private myTable As New DataTable()
Public Sub LoadXml(sender As Object, e As EventArgs) Handles Me.Load
With myTable.Columns
.Add("DisplayValue", GetType(String))
.Add("HiddenValue", GetType(Integer))
End With
myTable.DefaultView.Sort = "DisplayValue ASC"
ListBox1.DisplayMember = "DisplayValue"
ListBox1.ValueMember = "HiddenValue"
ListBox1.DataSource = myTable
Dim doc As New Xml.XmlDocument
doc.Load("c:\address.xml")
Dim xmlName As Xml.XmlNodeList = doc.GetElementsByTagName("name")
Dim xmlSurname As Xml.XmlNodeList = doc.GetElementsByTagName("surname")
Dim xmlId As Xml.XmlNodeList = doc.GetElementsByTagName("id")
For i As Integer = 0 To xmlName.Count - 1
Dim nazwa As String = xmlName(i).FirstChild.Value + " " + xmlSurname(i).FirstChild.Value
myTable.Rows.Add(nazwa, xmlId(i).FirstChild.Value)
MsgBox(myTable.Rows(i).Item(1).ToString)
Next i
ListBox1.Sorted = True
End Sub
Later in the code I have event:
Public Sub ListBox1_DoubleClick(sender As Object, e As EventArgs) Handles ListBox1.DoubleClick
End Sub
I would like to know how can I call id from DataTable for selected listbox item. I hope u understand what I mean since my english is not perfect :)
Since you have added the XML value id to the data table column HiddenValue and you have assigned HiddenValue as the ValueMember for the listbox, once a record is selected in the listbox, id will be available in the listbox's [SelectedValue][1] member. For example:
Public Sub ListBox1_DoubleClick(sender As Object, e As EventArgs) Handles ListBox1.DoubleClick
MsgBox("Selected Id: " & ListBox1.SelectedValue.ToString())
End Sub

looping through datagridview

Mine is a windows app. containing forms named BOM nd BOMSelected..
There is datagridview in BOM which contains checkbox column.. When the user selects checkbox, the selected rows should be seen in the datagridview of other form, SelectedBom..
I have coded but don't get it working.. Some error..
Can you please help ??
Your Help is greatly appreciated..
Here is what i have done !!
Public Class SelectedBom
Private Sub SelectedBom_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'HemDatabase1DataSet4.partno' table. You can move, or remove it, as needed.
'Me.PartnoTableAdapter.Fill(Me.HemDatabase1DataSet4.partno)
Dim count As Integer = 0
For j As Integer = 0 To BOM.dgv1.RowCount - 1
If BOM.dgv1.Rows(j).Cells(0).Value = True Then
Dim ro As New DataGridViewRow
DataGridView2.Rows.Add(ro)
For i As Integer = 0 To BOM.dgv1.ColumnCount - 1
Me.DataGridView2.Rows(count).Cells(i).Value = BOM.dgv1.Rows(j).Cells(i).Value
Next
count += 1
End If
Next
End Sub
End Class
Try,
For Each row As DataGridViewRow In BOM.dgv1.Rows
Dim obj(row.Cells.Count - 1) As Object
For i = 0 To row.Cells.Count - 1
obj(i) = row.Cells(i).Value
Next
Me.DataGridView2.Rows.Add(obj)
Next
EDIT:
Demo:
Add Button1 and DataGridView1 in BOM form
Public Class BOM
Public Class Sample
Public Property Satus As Boolean
Public Property Name As String
Public Property ID As Integer
End Class
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
SelectedBom.Show()
End Sub
Private Sub BOM_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim myList As New List(Of Sample)
myList.Add(New Sample() With {.ID = 1, .Name = "A"})
myList.Add(New Sample() With {.ID = 2, .Name = "B"})
myList.Add(New Sample() With {.ID = 3, .Name = "C"})
DataGridView1.DataSource = myList
End Sub
End Class
Add DataGridView1 in SelectBOM form
Public Class SelectedBom
Private Sub SelectedBom_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim i As Integer = 0
DataGridView1.AutoGenerateColumns = False
DataGridView1.Columns.Add("Name", "Name")
DataGridView1.Columns.Add("No", "No")
For Each row As DataGridViewRow In BOM.DataGridView1.Rows
If DirectCast(row.Cells(0).Value, Boolean) Then
DataGridView1.Rows.Add(row.Cells(1).Value, row.Cells(2).Value)
End If
Next
End Sub
End Class
Maybe instead of using the for each statement, you should instead use:
for istep as integer = 0 to datagridview.rowcount - 2
With the for each syntax, you can't assign a value to the individual row as you walk down the row.