2010-01-19 5 views
11

J'ai une zone de liste remplie à partir d'un pull SQLDATA, et il arrête certaines colonnes que je ne veux pas comme OBJECT_dfj, OBJECT_daskd. La clé est tout cela étant avec OBJECT_, est-il un moyen de les supprimer de la liste? Je ne peux pas changer mon instruction SQL.C# supprimer des éléments de la liste

i essayé ceci:

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

mais il m'a donné l'erreur:

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

+0

Comment est-elle peuplée, via le code ou la liaison de données? Est-ce WPF? WinForms? ASP.NET? – keithwarren7

+0

Winform et son remplissage à partir d'un SQLCOMMAND –

+0

Cela n'a aucun sens. WinForms ListBox ne peut contenir qu'une seule colonne de texte sauf si vous effectuez un dessin personnalisé. Êtes-vous concaténant le contenu de tous les champs, ou quoi? –

Répondre

0

Désolé les gars je devais ajuster la chaîne

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

Vous ne pouvez pas modifier les références dans un recenseur alors que vous énumérez dessus; vous devez garder une trace de ceux à enlever puis les enlever.

Voici un exemple du travail autour:

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

Mais si vous utilisez C# 3.5, on pourrait dire quelque chose comme ça.

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

l'a essayé, ne semble rien enlever –

+1

il a gagné Ne travaillez pas comme un travail de copier-coller, c'est un indice plus qu'une réponse car je n'ai pas d'IDE à portée de main. – gingerbreadboy

+0

cette méthode dose pas avoir une bonne performance, il énumérer les éléments de la liste deux fois ... –

0

L'erreur que vous obtenez signifie que

foreach (string item in listBox1.Items) 

doit être remplacé par

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

En d'autres termes, ne pas utiliser un foreach.

EDIT: Ajout castée chaîne dans le code ci-dessus

EDIT2: Puisque vous utilisez RemoveAt(), rappelez-vous que votre index pour la prochaine itération (variable i dans l'exemple ci-dessus) ne doivent pas augmenter (puisque vous venez Supprimé).

+0

son me donnant: Erreur Impossible de convertir le type «objet» en «chaîne». Une conversion explicite existe (manque-t-il une distribution?) –

+0

try chaîne item = (chaîne) listBox1.Items [i]; –

+0

Cela ne fonctionnera pas - il supprime des éléments, donc après la suppression des éléments [5], les éléments [6] ne pointeront pas vers l'élément suivant dans la liste originale. Au lieu de cela, vous devez itérer de la fin au début. – egrunin

0

Vous ne pouvez pas modifier une collection pendant que vous l'itérez avec foreach. Vous pouvez essayer d'utiliser une instruction for() régulière.

Vous devrez peut-être reculer de la fin de la collecte pour vous assurer de couvrir chaque élément de la collection et ne pas surcharger accidentellement la fin de la collecte après avoir retiré un élément (puisque la longueur changerait). Je ne me souviens pas si .NET comptabilise cette possibilité ou non.

19

Vous ne pouvez pas utiliser un recenseur, vous devez boucle à l'aide d'un index, en commençant par le dernier élément:

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

Le problème ici est que vous changez votre recenseur vous supprimez des éléments de la liste. Ceci n'est pas valide avec une boucle 'foreach'. Mais à peu près tout autre type de boucle sera OK.

Vous pouvez essayer quelque chose comme ceci:

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

Erreur 1 'objet' ne contient pas de définition pour 'Contient' et aucune méthode d'extension 'Contient' acceptant un premier argument de type 'objet' introuvable (manque-t-il une directive using ou une référence d'assembly?) –

2

Vous voulez itérer en arrière grâce à l'aide d'un compteur au lieu de foreach. Si vous faites une itération, vous devez ajuster le compteur lorsque vous supprimez des éléments.

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

Error 'objet' ne contient pas de définition pour 'Contient' et aucune méthode d'extension 'Contient' acceptant un premier argument de type 'objet' n'a été trouvée (manque-t-il une directive using ou une référence d'assembly?) –

+0

if (listBox1.Items [i] .Contains (removelistitem)) 'devrait lire' if (((string) listBox1.Items [i]). Contient (removelistitem)) '. –

+0

InvalidArgument = La valeur de '117' n'est pas valide pour 'index'. Nom du paramètre: index –

0

Vous pouvez essayer cette méthode:

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

Cela devrait être correct comme il simplement copie le contenu à une liste temporaire qui est ensuite utilisé pour le supprimer de la zone de liste. Tout le monde s'il vous plaît n'hésitez pas à mentionner les corrections car je ne suis pas sûr à 100% que c'est tout à fait correct, je l'ai utilisé il y a longtemps.

0

Votre question implique que vous êtes prêt à modifier d'autres parties du code, même si vous ne pouvez pas modifier l'instruction SQL lui-même. Au lieu de les supprimer de la collection ListBox, il peut être plus simple de les exclure en premier lieu. Ce code suppose que vous vous connectez à 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); 
    } 
} 

Mais si vous êtes absolument déterminé à le faire de cette façon que vous devriez vérifier cette question sur modifying an enumerable collection while iterating through it.

0

Vous pouvez essayer cela aussi, si vous ne voulez pas traiter avec le recenseur:

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

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

Avec ce code, vous pouvez supprimer tous les éléments de votre ... listbox Notez que vous devriez écrire cette Code en cas de clic de bouton:

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

Vous pouvez le faire en 1 ligne, en utilisant Linq

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

j'ai découvert la dure que si vos objets listbox sont attribués, vous devez supprimer la liaison via une source de données

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

... qui avant de faire la suppression:

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

Sans la "listBoxWork.DataSource = null; « ligne, je recevais, » la valeur ne tombe pas dans la plage attendue "

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 peut utiliser le code suivant aussi:

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

}

Questions connexes