I have been searching for days, for any possible reference or suggestions and everything I've come across hasn't worked.
The goal:
User will select options in ComboBox1 that will then determine the available options in ComboBox2, then will populate a list of operations in ListBox1.
When the user selects available operations in ListBox1, I need the output to be the sum of values (total time in minutes in this case) into a label for display.
The data used in stored in a local db. So far everything works with my comboboxes and the listbox.
Im attempting to get the Text value, of all selected items, in ListBox1 to output the numeric value in my table (column 4 "OperationsTime"), into a label that will display the sum of all the selections (Total Time In Minutes).
Some Things I have Tried From Other Posts:
Label9.Text = ListBox1.ValueMember
Label9.Text = ListBox1.ValueMember.ToString
Label9.Text = CType(ListBox1.SelectedItem, DataRowView).Row.Item("OperationsTime").ToString
Attempted using Double:
Dim Total As Double = 0
For Each Time As Integer In ListBox1.SelectedItems
Total += CDbl(Time.ToString.Substring(Time.ToString.LastIndexOf(",") + 1))
Next
Label9.Text = Total.ToString
Screen Shot of the Table: Operations Data Table
Below is my code:
Imports System.Data
Imports System.Configuration
Imports System.Data.SqlClient
Public Class MainHome
Private Function GetData(ByVal sql As String) As DataTable
Dim constr As String = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\hartj\Documents\visual studio 2015\Projects\TIMEMATRIX2.0\TIMEMATRIX2.0\TMX.mdf;Integrated Security=True"
Using con As SqlConnection = New SqlConnection(constr)
Using sda As SqlDataAdapter = New SqlDataAdapter(sql, con)
Dim dt As DataTable = New DataTable()
sda.Fill(dt)
Dim row As DataRow = dt.NewRow()
row(0) = 1
row(1) = "Please Select"
dt.Rows.InsertAt(row, 0)
Return dt
End Using
End Using
End Function
Private Sub MainHome_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
ComboBox1.DataSource = Me.GetData("SELECT SizeId, SizeName FROM Size")
ComboBox1.DisplayMember = "SizeName"
ComboBox1.ValueMember = "SizeId"
ComboBox2.Enabled = False
ComboBox3.Enabled = False
End Sub
Private Sub ComboBox1_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles ComboBox1.SelectionChangeCommitted
ComboBox2.DataSource = Nothing
ComboBox3.DataSource = Nothing
ComboBox2.Enabled = False
ComboBox3.Enabled = False
If ComboBox1.SelectedValue.ToString() <> "0" Then
Dim sql As String = String.Format("SELECT DetailLevelId, DetailLevelName FROM DetailLevel WHERE SizeId = {0}", ComboBox1.SelectedValue)
ComboBox2.DataSource = Me.GetData(sql)
ComboBox2.DisplayMember = "DetailLevelName"
ComboBox2.ValueMember = "DetailLevelId"
ComboBox2.Enabled = True
End If
End Sub
Private Sub ComboBox2_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles ComboBox2.SelectionChangeCommitted
ListBox1.DataSource = Nothing
ListBox1.Enabled = False
If ComboBox2.SelectedValue.ToString() <> "0" Then
Dim sql As String = String.Format("SELECT OperationsId, OperationsName, OperationsTime FROM Operations WHERE DetailLevelId = {0}", ComboBox2.SelectedValue)
ListBox1.DataSource = Me.GetData(sql)
ListBox1.ValueMember = "OperationsName"
ListBox1.ValueMember = "OperationsTime"
ListBox1.Enabled = True
Label9.Text = CType(ListBox1.SelectedValue, Integer).ToString
'Label.Text = CType(cbbank.SelectedItem, DataRowView).Row.Item("Account").ToString
End IF
End Sub
Dim totalOperationsTime As Double
For Each view As DataRowView In ListBox1.SelectedItems
totalOperationsTime += CDbl(view("OperationsTime"))
Next
There's no need to get the DataRow
from the DataRowView
because you can access the field values directly from the DataRowView
. It can and does do many of the same things that the DataRow
does.
That's the most conventional way but there are other options too. You could throw some LINQ at it:
Dim totalOperationsTime = ListBox1.SelectedItems.Cast(Of DataRowView)().
Sum(Function(view) CDbl(view("OperationsTime")))
It is somewhat annoying that the ValueMember
property only helps you get a value for the SelectedItem
. Here's a class I wrote some time ago that adds a GetItemValue
method that makes use of the ValueMember
much as the GetItemText
method does for the DisplayMember
:
Public Class ListBoxEx
Inherits ListBox
Public Function GetItemValue(item As Object) As Object
Dim index = Me.Items.IndexOf(item)
If (index <> -1 AndAlso Me.DataManager IsNot Nothing) Then
Return Me.FilterItemOnProperty(Me.DataManager.List(index), Me.ValueMember)
End If
Return Nothing
End Function
End Class
If you use that control instead of a regular ListBox
then you can do this:
Dim totalOperationsTime As Double
For Each item In ListBoxEx1.SelectedItems
totalOperationsTime += CDbl(ListBoxEx1.GetItemValue(item))
Next
or this:
Dim totalOperationsTime = ListBox1.SelectedItems.Cast(Of Object)().
Sum(Function(item) CDbl(ListBoxEx1.GetItemValue(item)))
One advantage of using that custom control is that you don't have to know what type the data source or its items are. You only have to know that the ValueMember
has been set.
I made a few changes to your code. It works with a ListBox. See comments for details.
' "Please Select" doesn't work well in the ListBox, I added it as an option
Private Shared Function GetData(ByVal sql As String, insertPleaseSelect As Boolean) As DataTable
Dim constr As String = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\hartj\Documents\visual studio 2015\Projects\TIMEMATRIX2.0\TIMEMATRIX2.0\TMX.mdf;Integrated Security=True"
Using con As SqlConnection = New SqlConnection(constr)
Using sda As SqlDataAdapter = New SqlDataAdapter(sql, con)
Dim dt As DataTable = New DataTable()
sda.Fill(dt)
If insertPleaseSelect Then
Dim row As DataRow = dt.NewRow()
row(0) = 1
row(1) = "Please Select"
dt.Rows.InsertAt(row, 0)
End If
Return dt
End Using
End Using
End Function
Private Sub MainHome_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
ComboBox1.DataSource = GetData("SELECT [SizeId], [SizeName] FROM [Size]", True)
ComboBox1.DisplayMember = "SizeName"
ComboBox1.ValueMember = "SizeId"
ComboBox2.Enabled = False
ListBox1.SelectionMode = SelectionMode.MultiSimple ' allow multi-select
End Sub
Private Sub ComboBox1_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles ComboBox1.SelectionChangeCommitted
ComboBox2.DataSource = Nothing
ComboBox2.Enabled = False
If ComboBox1.SelectedValue.ToString() <> "0" Then
Dim sql As String = String.Format("SELECT [DetailLevelId], [DetailLevelName] FROM [DetailLevel] WHERE [SizeId] = {0}", ComboBox1.SelectedValue)
ComboBox2.DataSource = GetData(sql, True)
ComboBox2.DisplayMember = "DetailLevelName"
ComboBox2.ValueMember = "DetailLevelId"
ComboBox2.Enabled = True
End If
End Sub
Private Sub ComboBox2_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles ComboBox2.SelectionChangeCommitted
ListBox1.DataSource = Nothing
ListBox1.Enabled = False
If ComboBox2.SelectedValue.ToString() <> "0" Then
Dim sql As String = String.Format("SELECT [OperationsId], [OperationsName], [OperationsTime] FROM [Operations] WHERE [DetailLevelId] = {0}", ComboBox2.SelectedValue)
ListBox1.DataSource = GetData(sql, False)
ListBox1.DisplayMember = "OperationsName" ' changed this from ValueMember to DisplayMember
ListBox1.ValueMember = "OperationsTime"
ListBox1.Enabled = True
ListBox1.ClearSelected() ' Every time the ListBox is populated, clear it
End If
End Sub
' Added this handler to respond to user input, not programmatic selection changes
Private Sub ListBox1_Click(sender As Object, e As EventArgs) Handles ListBox1.Click
' Here is the sum
Label9.Text = ListBox1.SelectedItems.OfType(Of DataRowView).Sum(Function(o) CType(o("OperationsTime"), Double))
End Sub
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.