Удаление элементов в коллекции на основе строки списка - PullRequest
0 голосов
/ 22 апреля 2020

Возникают проблемы при нажатии на кнопку удаления. Если потребуется больше моего кода, дайте мне знать. Я получаю эту ошибку в строке AddressList.Remove (selectedName):

System.ArgumentException: 'Аргумент' Ключ 'не является допустимым значением.

У меня есть перепробовал много вариантов, но не могу понять, почему это не работает. Я думаю, что это как-то связано с тем, как строки объединяются в списке. Мне нужно иметь возможность удалять записи из коллекции и списка. Любая помощь будет принята с благодарностью.

Module EmailCollection
Public AddressList As New Collection

Public Sub AddRecord(ByVal a As cAddress)
    Try
        AddressList.Add(a)
    Catch ex As Exception
        MessageBox.Show("Error: inputs must be characters valid in string format")
    End Try
End Sub

End Module
public class form1 

Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
        Dim frmAdd As New AddNewName

        frmAdd.ShowDialog()

        UpdateListBox()


    End Sub
Private Sub UpdateListBox()
        lstAddress.Items.Clear()

        Dim a As cAddress
        For Each a In AddressList
            lstAddress.Items.Add(String.Concat(a.strName, a.strEmail, a.strPhone, a.strComment))
        Next

        If lstAddress.Items.Count > 0 Then
            lstAddress.SelectedIndex = 0

        End If
    End Sub
Private Sub btnRemove_Click(sender As Object, e As EventArgs) Handles btnRemove.Click

        Dim selectedName As String
        Try
            ' Get the selected value.
            selectedName = lstAddress.SelectedItem.ToString()

            ' Remove the selected name from the list box and the collection.
            If MessageBox.Show("Are you sure?",
                               "Confirm Deletion",
                               MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.Yes Then

                lstAddress.Items.Remove(selectedName)
                AddressList.Remove(selectedName)
            End If

        Catch ex As NullReferenceException
            MessageBox.Show("Select an item to remove.", "Selection Needed")
        End Try
    End Sub
end class

Ответы [ 3 ]

0 голосов
/ 23 апреля 2020

Пост Карен кажется довольно полным. Мой ответ - попытка сосредоточиться на вашем прямом вопросе.

Я не вижу всех определений типов, показанных в вашем коде, но отвечаю на ваш вопрос, который, как мне кажется, звучит так: «Почему я получаю Систему? .ArgumentException: 'Аргумент' Ключ 'не является допустимым значением ":

В ошибочной строке кода:

AddressList.Remove(selectedName)

AddressList является коллекцией. Чтобы использовать .Remove, вы должны передать объект коллекции AddressList, чтобы удалить его. Вы передаете простую строку, и это не объект AddressList. Вам нужно создать объект на основе вашей строки selectedName, чтобы перейти в .Remove, и эта строка должна работать. Все остальное, что вы делаете, кажется более сложным.

0 голосов
/ 23 апреля 2020

В вашем модуле я изменил AddressList со старого типа VB6 Collection на. net List(Of T). T обозначает Type.

Module EmailCollection

    Public AddressList As New List(Of cAddress)

    Public Sub AddRecord(ByVal a As cAddress)
        AddressList.Add(a)
    End Sub

End Module

Я догадался, что ваш класс cAddress выглядит примерно так. Я добавил пользовательский метод .ToString, чтобы в списке отображались данные, которые вы будете sh, но сам элемент будет cAddress объектом.

Public Class cAddress
    Public Property strName As String
    Public Property strEmail As String
    Public Property strPhone As String
    Public Property strComment As String

    Public Overrides Function ToString() As String
        Return $"{strName}, {strEmail}, {strPhone}, {strComment}"
    End Function
End Class

В форме ...

Вместо добавления строки в список я добавил объект cAddress. Окно списка вызывает .ToString для объекта, чтобы получить отображаемое значение.

Private Sub UpdateListBox()
    ListBox1.Items.Clear()
    For Each a As cAddress In AddressList
        ListBox1.Items.Add(a)
    Next
    If ListBox1.Items.Count > 0 Then
        ListBox1.SelectedIndex = 0
    End If
End Sub

В кнопке удаления я приведу выбранный элемент к его базовому типу, cAddress. Этот предмет удален из AddressList. Затем просто удалите выбранный элемент из списка.

Private Sub btnRemove_Click(sender As Object, e As EventArgs) Handles btnRemove.Click
    If MessageBox.Show("Are you sure?",
                           "Confirm Deletion",
                           MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.Yes Then
        AddressList.Remove(DirectCast(ListBox1.SelectedItem, cAddress))
        ListBox1.Items.Remove(ListBox1.SelectedItem)
    End If
End Sub

Я изменил имя списка на ListBox1 в соответствии с моим тестовым проектом.

0 голосов
/ 22 апреля 2020

Вот что попробовать, используйте BindingSource для настройки ListBox. В классе переопределите ToString на то, что должно отображаться в ListBox, а не на то, что вы делаете сейчас без DataSource.

Моя версия вашего класса содержит изменения имени и имени свойства.

Public Class Address
    Public Property Name() As String
    Public Property Email() As String
    Public Property Phone() As String
    Public Property Comment() As String

    Public Overrides Function ToString() As String
        Return $"{Name} {Email} {Phone} {Comment}"
    End Function
End Class

Проверенные данные используются для заполнения ListBox

Public Class Form1
    Private ReadOnly _bsAddresses As New BindingSource

    Private Sub UpdateListBox()
        Dim AddressList = New List(Of Address) From
                {
                    New Address() With {
                        .Name = "John",
                        .Email = "john@gmail.com",
                        .Phone = "555-444-3456",
                        .Comment = "AAA"},
                    New Address() With {
                        .Name = "Mary",
                        .Email = "mary@gmail.com",
                        .Phone = "888-333-2222",
                        .Comment = "BBB"},
                    New Address() With {
                        .Name = "Bob",
                        .Email = "bob@gmail.com",
                        .Phone = "111-555-9999",
                        .Comment = "CCC"}
                }

        _bsAddresses.DataSource = AddressList

        lstAddress.DataSource = _bsAddresses

        lstAddress.SelectedIndex = 0

    End Sub

    Private Sub Form1_Shown(sender As Object, e As EventArgs) _
        Handles Me.Shown

        UpdateListBox()

    End Sub

    Private Sub RemoveButton_Click(sender As Object, e As EventArgs) _
        Handles RemoveButton.Click

        If lstAddress.Items.Count > 0 AndAlso lstAddress.SelectedItem IsNot Nothing Then
            Dim address = CType(_bsAddresses.Current, Address)
            If My.Dialogs.Question($"Remove {address.Name}") Then
                _bsAddresses.RemoveCurrent()
                RemoveButton.Enabled = _bsAddresses.Count > 0
            End If
        End If

    End Sub
End Class

Модуль кода для задания вопроса

Namespace My
    <ComponentModel.EditorBrowsable(ComponentModel.EditorBrowsableState.Never)>
    Partial Friend Class _Dialogs
        Public Function Question(text As String) As Boolean
            Return (MessageBox.Show(
                text,
                My.Application.Info.Title,
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question,
                MessageBoxDefaultButton.Button2) = MsgBoxResult.Yes)
        End Function
    End Class
    <HideModuleName()>
    Friend Module WinFormsDialogs
        Private instance As New ThreadSafeObjectProvider(Of _Dialogs)
        ReadOnly Property Dialogs() As _Dialogs
            Get
                Return instance.GetInstance()
            End Get
        End Property
    End Module
End Namespace

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...