locked
Edit item in listbox without adding new item RRS feed

  • Question

  • Hey. So I have a data bound Listbox attached to an access database (Listbox uses single Datatable column as a means of identification of the item). When I click the "Add" button the Datatable gets a new row added to it, and the text is coming from textboxes on my form. Thus the Listbox automatically updates to retrieve the new information from the Datatable. I also have an "Edit" button that gets the Selectedindex of an item in the Listbox and compares it to the row(inc) in the Datatable based on the parameter of "inc" which I've declared to be the Selectedindex of the item in the Listbox. So

    If Listbox.Items.Contains(LoginDBDataSet.Tables("Notice").Rows(inc).Item(1).ToString)

    // I think the problem lies somewhere in this line ^

    This adds it to the textboxes ready for editing. Now when I click the "Add" button, again, my aim is to check the Listbox for any items equal to the respective field in the Datatable. Thus is any item does exist in the Listbox that is also in the Datatable, it basically edits it without adding an entire new item. So

    DataSet.Tables("Notice").Rows(inc).Item(1) = txt_notes_title.Text
    DataSet.Tables("Notice").Rows(inc).Item(2) = txt_notes_body.Text

    This is my finalised code which I'm stuck on:

        Private Sub btn_notes_addnew_Click(sender As Object, e As EventArgs) Handles btn_notes_addnew.Click
    
            ' // Notice how we dont add to the actual listbox or any other controls, rather update the database which automatically updates the control
            Dim inc As Integer = Lb_NotesList.SelectedIndex
    
            For Each item In Lb_NotesList.Items
    
                If item.Contains(DBDataSet.Tables("Notice").Rows(inc).Item(1).ToString) Then
                    MsgBox("// Item has been replaced // SelectedIndex  = " & Lb_NotesList.SelectedIndex)
                    'txt_notes_title.Text = Lb_NotesList.SelectedValue.ToString()
                    DBDataSet.Tables("Notice").Rows(inc).Item(2) = txt_notes_body.Text
                    DBDataSet.Tables("Notice").Rows(inc).Item(1) = txt_notes_title.Text
    
                    Me.Validate()
                    Me.NoticeBindingSource.EndEdit()
                    Me.NoticeTableAdapter.Update(Me.DBDataSet)
    
                Else
                    MsgBox("// Second Item added // SelectedIndex  = " & Lb_NotesList.SelectedIndex)
                    Dim dsNewRow As DataRow
    
                    dsNewRow = Me.DBDataSet.Tables("Notice").NewRow()
                    dsNewRow.Item("Title") = txt_notes_title.Text
                    dsNewRow.Item("Body Text") = txt_notes_body.Text
                    Me.DBDataSet.Tables("Notice").Rows.Add(dsNewRow)
    
                    Me.Validate()
                    Me.NoticeBindingSource.EndEdit()
                    Me.NoticeTableAdapter.Update(Me.DBDataSet)
                End If
    
            Next
    
        End Sub
        Private Sub btn_notes_editnotes_Click(sender As Object, e As EventArgs) Handles btn_notes_editnotes.Click
    
            Dim inc As Integer = Lb_NotesList.SelectedIndex
    
            MsgBox("Item being edited // SelectedIndex /inc = " & Lb_NotesList.SelectedIndex)
            txt_notes_title.Text = Lb_NotesList.SelectedValue.ToString()
            txt_notes_body.Text = DBDataSet.Tables("Notice").Rows(inc).Item(2)
    
        End Sub

    As soon as I press the add button the first time I get this error:

    An unhandled exception of type 'System.MissingMemberException' occurred in Microsoft.VisualBasic.dll

    Additional information: Public member 'Contains' on type 'DataRowView' not found.

    Furthermore it highlights this segment of code:

    If item.Contains(LoginDBDataSet.Tables("Notice").Rows(inc).Item(1).ToString) Then

    If anyone has any clue as to why this is happening and how I can fix it, I would really appreciate it.

    Thanks, Faizan


    Friday, February 28, 2014 11:26 AM

Answers

  • .....

    What I did was give you an example, not something you just blindly copy.

    this

     If DirectCast(Lb_NotesList.Items(0), DataRowView).Item(inc).ToString() = LoginDBDataSet.Tables("Notice").Rows(inc).Item(1).ToString Then

    should ofc be

     If DirectCast(item, DataRowView).Item(inc).ToString() = LoginDBDataSet.Tables("Notice").Rows(inc).Item(1).ToString Then


    This example ofc still implies that you are using the for next loop ....
    • Proposed as answer by Mr. Monkeyboy Friday, February 28, 2014 2:57 PM
    • Edited by Rbie Friday, February 28, 2014 3:03 PM
    • Marked as answer by MasterSplint3r Friday, February 28, 2014 3:47 PM
    Friday, February 28, 2014 2:51 PM

All replies

  • actually the error says it already, item doesn't have a .contains property and since Item is one 1

    contains wouldn't make much sense now would it

    so

    If DirectCast(ListBox1.Items(0), DataRowView).Item(0).ToString() = LoginDBDataSet.Tables("Notice").Rows(inc).Item(1).ToString) Then
    Friday, February 28, 2014 12:19 PM
  • actually the error says it already, item doesn't have a .contains property and since Item is one 1

    contains wouldn't make much sense now would it

    so

    If DirectCast(ListBox1.Items(0), DataRowView).Item(0).ToString() = LoginDBDataSet.Tables("Notice").Rows(inc).Item(1).ToString) Then

    Thanks, that solved the problem of comparing them, but I now am getting another error. However I don't quite understand what the "ListBox1.Items(0)" meant.

    I tried using the code as:

    If DirectCast(Lb_NotesList.Items(0), DataRowView).Item(inc).ToString() = LoginDBDataSet.Tables("Notice").Rows(DBinc).Item(1).ToString Then

    So with a few modifications I tried a way to add an item to the Listbox on the first click of "Add" and all that follow will use the comparison. This is because if I just put the comparison on the first click of "Add" there would be no Selectedindex since the Listbox would be empty. Count is declared at the top of my class as = -1. Here is the new code:

        Private Sub btn_notes_addnew_Click(sender As Object, e As EventArgs) Handles btn_notes_addnew.Click
    
            count = count + 1
    
            ' // Notice how we dont add to the actual listbox or any other controls, rather update the database which automatically updates the control
            If count = 0 Then
    
                'Adds First Item to remove -1 index and set it to a new 0
                MsgBox("First Item added")
                Dim dsNewRow As DataRow
    
                dsNewRow = Me.LoginDBDataSet.Tables("Notice").NewRow()
                dsNewRow.Item("Title") = txt_notes_title.Text
                dsNewRow.Item("Body Text") = txt_notes_body.Text
                Me.LoginDBDataSet.Tables("Notice").Rows.Add(dsNewRow)
    
                Me.Validate()
                Me.NoticeBindingSource.EndEdit()
                Me.NoticeTableAdapter.Update(Me.LoginDBDataSet)
    
                count = count + 1
    
            End If
    
            If count > 1 Then
    
                Dim inc As Integer = Lb_NotesList.SelectedIndex
    
                For Each item In Lb_NotesList.Items
                    If DirectCast(Lb_NotesList.Items(0), DataRowView).Item(inc).ToString() = LoginDBDataSet.Tables("Notice").Rows(inc).Item(1).ToString Then
    
                        MsgBox("// Similar item found in listbox that is also in DB // Item has been replaced // SelectedIndex  = " & Lb_NotesList.SelectedIndex)
                        LoginDBDataSet.Tables("Notice").Rows(inc).Item(2) = txt_notes_body.Text
                        LoginDBDataSet.Tables("Notice").Rows(inc).Item(1) = txt_notes_title.Text
    
                        Me.Validate()
                        Me.NoticeBindingSource.EndEdit()
                        Me.NoticeTableAdapter.Update(Me.LoginDBDataSet)
    
                    Else
                        MsgBox("No similar item found in listbox that is also in DB")
                        MsgBox("// Item added // SelectedIndex  = " & Lb_NotesList.SelectedIndex)
                        Dim dsNewRow As DataRow
    
                        dsNewRow = Me.LoginDBDataSet.Tables("Notice").NewRow()
                        dsNewRow.Item("Title") = txt_notes_title.Text
                        dsNewRow.Item("Body Text") = txt_notes_body.Text
                        Me.LoginDBDataSet.Tables("Notice").Rows.Add(dsNewRow)
    
                        Me.Validate()
                        Me.NoticeBindingSource.EndEdit()
                        Me.NoticeTableAdapter.Update(Me.LoginDBDataSet)
    
                    End If
                Next
    
            End If
    
        End Sub

    The first time I click the "Add" button, it successfully adds the title to the datatable and hence the Listbox. But the second time I go to add a new item - with a new name or even the same I get this:

    An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll

    Additional information: List that this enumerator is bound to has been modified. An enumerator can only be used if the list does not change.

    EDIT: I removed the For/Next loop and all errors are gone and the first item adds fine. But when I edit any item and press "Add" it does not replace it on the database, but rather adds a new item.





    Friday, February 28, 2014 2:22 PM
  • .....

    What I did was give you an example, not something you just blindly copy.

    this

     If DirectCast(Lb_NotesList.Items(0), DataRowView).Item(inc).ToString() = LoginDBDataSet.Tables("Notice").Rows(inc).Item(1).ToString Then

    should ofc be

     If DirectCast(item, DataRowView).Item(inc).ToString() = LoginDBDataSet.Tables("Notice").Rows(inc).Item(1).ToString Then


    This example ofc still implies that you are using the for next loop ....
    • Proposed as answer by Mr. Monkeyboy Friday, February 28, 2014 2:57 PM
    • Edited by Rbie Friday, February 28, 2014 3:03 PM
    • Marked as answer by MasterSplint3r Friday, February 28, 2014 3:47 PM
    Friday, February 28, 2014 2:51 PM
  • "What I did was give you an example, not something you just blindly copy."


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

    Friday, February 28, 2014 2:58 PM
  • Sorry, I was looking around for how to use the syntax properly. I'm guessing 'item' here is the one declared in the For/Next loop: DirectCast(item, DataRowView).Item(inc).ToString().

    But even so, I do not understand whats going wrong here it still gives me the enumerator error. Meaning it goes through the count = 0 block perfectly, but halts at when count > 1. This is what exactly happens when I click Add the second time. It skips the comparison  (I know this because I see the message "No similar items found in listbox" which I set up, which means it goes to the Else Block; but here is where I get the error and it makes no sense to me (Or anything that I can think of).


    Friday, February 28, 2014 3:04 PM
  • yes what that error means that if you use

    for each whateveritem in whateverlist

    you cannot modify that list (since modifing the list could disrupt the loop, same reason why you cannot delete anything in that list while looping it

    you can get around that by not using the enumerator and just loop by index

    like

     For yy as integer = 0 to Lb_NotesList.Items.count-1

    Friday, February 28, 2014 3:12 PM
  • hmm I just noticed that you are actually adding stuff to the list while looping it, you understand that probably won't work haven't tested it, but that is a very dangerous situation and could lead to infinite loops

    basicaly you are changing the upper limit of the loop while looping it

    example

    dim x as integer = 10

    for y as integer = 0 to x

    x+=1

    next

    you understand that this is a disasterous scenario ?

    Friday, February 28, 2014 3:21 PM
  • -.- Yes. I'm pretty sure my idea of implementing this is just flawed beyond reality.
    Friday, February 28, 2014 3:25 PM
  • Modern programming is with bound data. 

    You use references to show that data. 

    But all updates you do with the original data and you leave the controls alone.

    Therefore I miss the most important part in your code


    TheListBox.DataSource = DBDataSet.Tables("Notice")
    TheListBox.DisplayMember = "TheNameOfTheDisplayColumn"

    And avoid using Class names as object name.

    Mostly it goes well, but sometimes not.


    Success
    Cor

    Friday, February 28, 2014 3:34 PM