С# удаление элементов из списка

У меня есть список, который заполняется из SQLDATA pull, и он вытягивает несколько столбцов, которые мне не нужны, как OBJECT_dfj, OBJECT_daskd. Ключ - все это с OBJECT_, есть ли способ удалить их из списка? Я не могу изменить свою инструкцию SQL.

Я пробовал это:

 foreach (string item in listBox1.Items)
 {
     string removelistitem = "OBJECT";
     if(item.Contains(removelistitem))
     {
         listBox1.Items.Remove(item);
     }
 }

но это дало мне ошибку:

Перечислите, что этот перечислитель связан с изменением. Перечислитель может использоваться только в том случае, если список не изменяется.

Ответ 1

Извините, ребята, мне пришлось отрегулировать строку

sqldatapull = dr[0].ToString();
                if (sqldatapull.StartsWith("OBJECT"))
                {
                    sqldatapull = "";
                }
                listBox1.Items.Add(sqldatapull);
                for (int i = listBox1.Items.Count - 1; i >= 0; i--)
                {
                    if (String.IsNullOrEmpty(listBox1.Items[i] as String))
                        listBox1.Items.RemoveAt(i);
                }
            }

Ответ 2

Вы не можете использовать перечислитель, вам нужно циклически использовать индекс, начиная с последнего элемента:

for (int n = listBox1.Items.Count - 1; n >= 0; --n)
{
    string removelistitem = "OBJECT";
    if (listBox1.Items[n].ToString().Contains(removelistitem))
    {
        listBox1.Items.RemoveAt(n);
    }
}

Ответ 3

Вы не можете изменять ссылки в перечислителе, пока вы перечисляете его; Вы должны следить за теми, чтобы удалить, а затем удалить их.

Это пример обходного пути:

List<string> listbox = new List<string>();
List<object> toRemove = new List<object>();

foreach (string item in listbox)
{
    string removelistitem = "OBJECT";
    if (item.Contains(removelistitem))
    {
        toRemove.Add(item);
    }
}

foreach (string item in toRemove)
{
    listbox.Remove(item);
}

Но если вы используете С# 3.5, вы можете сказать что-то вроде этого.

listbox.Items = listbox.Items.Select(n => !n.Contains("OBJECT"));

Ответ 4

Вы хотите итерации назад, используя счетчик вместо foreach. Если вы перебираете вперед, вам нужно отрегулировать счетчик при удалении элементов.

for(int i=listBox1.Items.Count - 1; i > -1; i--) {
{
    if(listBox1.Items[i].Contains("OBJECT"))
    {
        listBox1.Items.RemoveAt(i);
    }
}

Ответ 5

Ошибка, которую вы получаете, означает, что

foreach (string item in listBox1.Items)

следует заменить на

for(int i = 0; i < listBox1.Items.Count; i++) {
    string item = (string)listBox1.Items[i];

Другими словами, не используйте foreach.

EDIT: добавлен листинг в строку в коде выше

EDIT2: поскольку вы используете RemoveAt(), помните, что ваш индекс для следующей итерации (переменная я в приведенном выше примере) не должен увеличиваться (поскольку вы просто удалили его).

Ответ 6

Вы не можете изменять коллекцию, пока вы выполняете ее с помощью foreach. Вы можете попробовать использовать регулярный оператор for().

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

Ответ 7

Проблема заключается в том, что вы изменяете свой счетчик при удалении элементов из списка. Это неверно в цикле "foreach". Но практически любой другой тип цикла будет в порядке.

Итак, вы можете попробовать что-то вроде этого:

for(int i=0; i < listBox1.Items.Count; )
{
    string removelistitem = "OBJECT";
    if(listBox1.Items[i].Contains(removelistitem))
         listBox1.Items.Remove(item);
    else
        ++i;
}

Ответ 8

Вы можете попробовать этот метод:

List<string> temp = new List<string>();

    foreach (string item in listBox1.Items)
    {
        string removelistitem = "OBJECT";
        if(item.Contains(removelistitem))
        {
            temp.Items.Add(item);
         }
     }

    foreach(string item in temp)
    {
       listBox1.Items.Remove(item);
    }

Это должно быть правильно, поскольку оно просто копирует содержимое во временный список, который затем используется для его удаления из ListBox.

Все остальные, пожалуйста, не стесняйтесь упоминать исправления, так как я не на 100% уверен, что он полностью прав, я использовал его давным-давно.

Ответ 9

В вашем вопросе подразумевается, что вы хотите изменить другие части кода, даже если вы не можете изменять сам SQL-запрос. Вместо того, чтобы удалять их из коллекции ListBox, было бы проще просто исключить их в первую очередь. Этот код предполагает, что вы подключаетесь к SQL Server:

void PopulateListBox(ListBox listToPopulate)
{
    SqlConnection conn = new SqlConnection("myConnectionString"); 
    SqlCommand cmd = new SqlCommand("spMyStoredProc", conn);
    cmd.CommandType = CommandType.StoredProcedure;
    SqlDataReader reader = cmd.ExecuteReader();
    while (reader.Read())
    {
        string item = reader.GetString(0); //or whatever column is displayed in the list
        if (!item.Contains("OBJECT_"))
            listToPopulate.Items.Add(item); 
    }
}

Но если вы решительно настроены так сделать, вы должны проверить этот вопрос на изменении перечислимой коллекции, итерации через нее.

Ответ 10

Вы также можете попробовать это, если вы не хотите иметь дело с перечислителем:

object ItemToDelete = null;
foreach (object lsbItem in listbox1.Items)
{
   if (lsbItem.ToString() == "-ITEM-")
   {
      ItemToDelete = lsbItem;                                  
   }
}

if (ItemToDelete != null)
    listbox1.Items.Remove(ItemToDelete);

Ответ 11

С помощью этого кода вы можете удалить каждый элемент из своего списка... Обратите внимание, что вы должны написать этот код в событии клика вашей кнопки:

        if (listBox1.SelectedIndex != -1)
        {
            listBox1.Items.RemoveAt(listBox1.SelectedIndex);
        } 

Ответ 12

Вы можете сделать это в 1 строке, используя Linq

listBox1.Cast<ListItem>().Where(p=>p.Text.Contains("OBJECT")).ToList().ForEach(listBox1.Items.Remove);

Ответ 13

Я обнаружил, что, если ваши элементы списка назначены через источник данных

List<String> workTables = hhsdbutils.GetWorkTableNames();
listBoxWork.DataSource = workTables;

... вам нужно отменить это, прежде чем делать удаление:

listBoxWork.DataSource = null;
for (int i = listBoxWork.Items.Count - 1; i >= 0; --i)
{
    if (listBoxWork.Items[i].ToString().Contains(listboxVal))
    {
        listBoxWork.Items.RemoveAt(i);
    }
}

Без строки "listBoxWork.DataSource = null;" я получал: "Значение не попадает в ожидаемый диапазон"

Ответ 14

protected void lbAddtoDestination_Click(object sender, EventArgs e)
        {
            AddRemoveItemsListBox(lstSourceSkills, lstDestinationSkills);
        }
        protected void lbRemovefromDestination_Click(object sender, EventArgs e)
        {
            AddRemoveItemsListBox(lstDestinationSkills, lstSourceSkills);
        }
        private void AddRemoveItemsListBox(ListBox source, ListBox destination)
        {
            List<ListItem> toBeRemoved = new List<ListItem>();
            foreach (ListItem item in source.Items)
            {
                if (item.Selected)
                {
                    toBeRemoved.Add(item);
                    destination.Items.Add(item);
                }
            }
            foreach (ListItem item in toBeRemoved) source.Items.Remove(item);
        }

Ответ 15

Вы также можете использовать следующий код:

 foreach (var item in listBox1.Items.Cast<string>().ToList())
 {
     string removelistitem = "OBJECT";
     if (item.Contains(removelistitem))
     {
        listBox1.Items.Remove(item);
     }
 }

Ответ 16

   for (int i = 0; i < listBox1.Items.Count; i++)
    {
        if (textBox1.Text == listBox1.Items[i].ToString())
        {
            jeElement = true;
            break;
        }
    }
    if (jeElement)
    {
        label1.Text = "je element";
    }
    else
    {
        label1.Text = "ni element";
    }
    textBox1.ResetText();
    textBox1.Focus();

}

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Alt == true && e.KeyCode == Keys.A)
    {
        buttonCheck.PerformClick();
    }
}

}