简体   繁体   中英

Trying to get SUM of ListBox selected items from local DataTable into a Label

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:

  1.  Label9.Text = ListBox1.ValueMember
  2.  Label9.Text = ListBox1.ValueMember.ToString
  3.  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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM