2010-01-19 23 views
11

Ho una casella di riepilogo popolata da un comando SQLDATA, e tira giù alcune colonne che non desidero come OBJECT_dfj, OBJECT_daskd. La chiave è che tutti questi sono con OBJECT_, c'è un modo per rimuoverli dalla listbox? Non riesco a modificare la mia dichiarazione SQL.C# rimozione degli elementi dalla listbox

ho provato questo:

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

ma mi ha dato l'errore:

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

+0

Come si viene popolata, tramite codice o associazione dati? È questo WPF? WinForms? ASP.NET? – keithwarren7

+0

Winform, e viene popolato da un SQLCOMMAND –

+0

Questo non ha alcun senso. Il ListBox WinForms può contenere solo una colonna di testo a meno che tu non stia facendo un disegno personalizzato. Stai concatenando il contenuto di tutti i campi o cosa? –

risposta

0

Scusate ragazzi ho dovuto regolare la stringa di

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); 
       } 
      } 
5

Non è possibile modificare i riferimenti in un enumeratore mentre si enumerano su di esso; devi tenere traccia di quelli da rimuovere e rimuoverli.

Questo è un esempio del lavoro intorno:

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); 
     } 

Ma se si sta utilizzando C# 3.5, si potrebbe dire qualcosa di simile.

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

provato, non sembra rimuovere nulla –

+1

ha vinto Lavorare come un lavoro di copia e incolla, è un indizio più di una risposta, perché non ho un IDE a portata di mano. – gingerbreadboy

+0

questo metodo non ha una buona prestazione, enumera le voci di elenco due volte ... –

0

L'errore che si stanno ottenendo significa che

foreach (string item in listBox1.Items) 

dovrebbe essere sostituito con

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

In altre parole, non usare un foreach.

EDIT: aggiunto cast stringa nel codice sopra

EDIT2: Dal momento che si sta utilizzando RemoveAt(), ricordate che il vostro indice per la prossima iterazione (variabile i nell'esempio di cui sopra) non devono incrementare (dato che solo cancellato).

+0

mi dà: Errore Impossibile convertire implicitamente il tipo 'oggetto' in 'stringa'. Esiste una conversione esplicita (ti manca un cast?) –

+0

try string item = (stringa) listBox1.Items [i]; –

+0

Questo non funziona: sta rimuovendo gli articoli, quindi dopo aver rimosso gli articoli [5], gli articoli [6] non puntano all'elemento successivo nell'elenco originale. Invece, devi scorrere dalla fine all'inizio. – egrunin

0

Non è possibile modificare una raccolta mentre si sta iterando su di essa con foreach. Potresti provare a utilizzare un'istruzione for() regolare.

Potrebbe essere necessario scorrere a ritroso dalla fine della raccolta per assicurarsi di coprire ogni elemento della raccolta e non superare inavvertitamente la fine della raccolta dopo aver rimosso un elemento (poiché la lunghezza sarebbe cambiata). Non riesco a ricordare se .NET conti per quella possibilità o meno.

19

Non è possibile utilizzare un enumeratore, bisogna ciclo utilizzando un indice, a partire l'ultimo elemento:

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

Il problema qui è che si sta cambiando la vostra enumerator come si rimuovono elementi dal elenco. Questo non è valido con un ciclo 'foreach'. Ma praticamente qualsiasi altro tipo di loop andrà bene.

Così si potrebbe provare qualcosa di simile:

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

Errore 1 "oggetto" non contiene una definizione per "Contiene" e non è possibile trovare alcun metodo di estensione "Contiene" che accetta un primo argomento di tipo "oggetto" (manca una direttiva using o un riferimento all'assembly?) –

2

Si vuole iterare a ritroso attraverso l'utilizzo di un contatore invece di foreach. Se si esegue l'iterazione in avanti, è necessario regolare il contatore mentre si eliminano gli elementi.

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

Errore "oggetto" non contiene una definizione per "Contiene" e non è possibile trovare alcun metodo di estensione "Contiene" che accetta un primo argomento di tipo "oggetto" (manca una direttiva using o un riferimento all'assembly?) –

+0

Credo " if (listBox1.Items [i] .Contains (removelistitem)) 'dovrebbe leggere' if (((stringa) listBox1.Items [i]). Contains (removelistitem)) '. –

+0

InvalidArgument = Il valore di '117' non è valido per 'index'. Nome parametro: indice –

0

Si potrebbe provare questo metodo:

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); 
    } 

Questo dovrebbe essere corretto come esso copia semplicemente il contenuto in una lista temporanea, che viene poi utilizzato per eliminarlo dalla casella di riepilogo.

Tutti gli altri si sentono liberi di citare le correzioni perché non sono sicuro al 100% che sia completamente corretto, l'ho usato molto tempo fa.

0

La tua domanda implica che siete disposti a modificare altri parti del codice, anche se non è possibile modificare l'istruzione SQL in sé. Invece di rimuoverli dalla raccolta di ListBox, potrebbe essere più semplice escluderli in un primo momento. Questo codice presuppone che si sta collegando a 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); 
    } 
} 

Ma se siete assolutamente determinato a farlo in questo modo si dovrebbe verificare questa domanda modifying an enumerable collection while iterating through it.

0

Si può provare questo anche, se non si vuole affrontare l'enumeratore:

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

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

Con questo codice è possibile rimuovere ogni elemento dalla casella di riepilogo ... noti che si dovrebbe scrivere questo codice all'evento di click del pulsante:

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

lo si può fare in 1 linea, utilizzando Linq

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

Ho trovato il modo duro che se i tuoi articoli ListBox vengono assegnati tramite una fonte di dati

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

... bisogna svincolare che prima di fare la rimozione:

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

Senza il "listBoxWork.DataSource = null; "linea, mi è stato sempre," valore non rientra nell'intervallo previsto "

0
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); 
     } 
0

Yo u possibile utilizzare il codice seguente troppo:

foreach (var item in listBox1.Items.Cast<string>().ToList()) 
{ 
    string removelistitem = "OBJECT"; 
    if (item.Contains(removelistitem)) 
    { 
     listBox1.Items.Remove(item); 
    } 
} 
0
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(); 
    } 
} 

}

Problemi correlati