2

Given a class like so

Public Class ItemPanel

    Inherits Panel

    Public Name as string
    Public Quantity As Integer

End Class

And a list like so

Public li_ip As New List(Of ItemPanel)

I have a sub will help me add ItemPanel to li_ip list when a button clicked, every button clicked will also add their text into li_item, so when a button click twice, only the first time will add ItemPanel to li_ip, second click will only change the quantity in ItemPanel

Private Sub RefreshOrdered(sender As Object)
        If Not li_item.Contains(sender.Text) Then

            Dim pn As ItemPanel
            With pn
                .Name = sender.Text
                .Quantity = 1
            End With

            li_ip.Add(pn)

        Else

            'Here I want to change the quantity in ItemPanel depend on the sender.Text

        End If
End Sub

So how can I get the result I want? What should I write after else?

vbnewbie
  • 206
  • 6
  • 26
  • 1
    To get the item from the list this answer will help: http://stackoverflow.com/a/200165/5152045 – Neal Dec 16 '16 at 13:00
  • Seems to me like you want a `Dictionary(Of String, Integer)`. Have you checked containers other than `List`? – default Dec 16 '16 at 16:49

1 Answers1

5

To search for an list item by one of its properties the List(Of T).Find Method can be used. In this case the List is referenced by variable li_ip and the property which is used to find the list item is the Name.

According to the MSDN documentation the Find method returns the first element that matches the conditions defined by the specified predicate, if found; otherwise, the default value for type T.

Default value of T which is ItemPanel is Nothing becasue ItemPanel is a reference type. So when Find actually finds the item then its Quantity can be incremented. HTH

Dim itm As ItemPanel = li_ip.Find(function(c) c.Name = sender.Text)
If Not itm Is Nothing Then
    itm.Quantity = itm.Quantity + 1   
End If 

Complete code could look like this.

Private Sub RefreshOrdered(sender As Object)
    ' Notice that Contains like this won't work:
    If Not li_ip.Contains(sender.Text) Then

        Dim pn As ItemPanel
        ' shouldn't here the New keyword be used?
        ' pn = New ItemPanel()  
        With pn
            .Name = sender.Text
            .Quantity = 1
        End With

        li_ip.Add(pn)

    Else

        'Here I want to change the quantity in ItemPanel depend on the sender.Text
        Dim itm As ItemPanel = li_ip.Find(function(c) c.Name = sender.Text)
        If Not itm Is Nothing Then
            itm.Quantity = itm.Quantity + 1   
        End If 

    End If
End Sub 

Note: LINQ can be used as well, but maybe Find is faster. See e.g. this answer.


EDIT:

Here is refactored version where the method Find is called just once like @Default has mentioned.

Private Sub RefreshOrdered(sender As Object)
    Dim panelName As string = sender.Text
    Dim panel As ItemPanel = li_ip.Find(function(p) p.Name = panelName) 
    If Not panel Is Nothing Then
        ' Panel with given name exists already in list, increment Quantity
        panel.Quantity += 1   
    Else 
        ' Panel with such name doesn't exist in list yet, add new one with this name
        Dim newPanel As ItemPanel
        newPanel = New ItemPanel()  
        With newPanel
            .Name = panelName
            .Quantity = 1
        End With
        li_ip.Add(newPanel)
    End If 
End Sub

Alternatively LINQ can be used instaed of Find, e.g. like this:

Dim panel As ItemPanel = li_ip.SingleOrDefault(function(p) p.Name = panelName)
Community
  • 1
  • 1
Daniel Dušek
  • 13,683
  • 5
  • 36
  • 51
  • Could you add some text explaining *why* you used that code? – vbnet3d Dec 16 '16 at 15:09
  • maybe you should call `Find` first and check if the returned value is `null`. Right now you are traversing the list twice (once with `.Contains` and then with `.Find`), which seems unnecessary. – default Dec 16 '16 at 16:18
  • @Default yes you are absolutely right! I just wanted to answer the question in the way it was build. But yes, the code could be refactored this way. – Daniel Dušek Dec 16 '16 at 16:18