Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I have made it work to delete attachment but can not delete listitem Error: Collection was modified; enumeration operation may not execute.

 private void DeleteFromSharePointList(HyperLink hp)
    {
        {

            SPWeb web = SPContext.Current.Web;
            web.AllowUnsafeUpdates = false;

            SPList myList = web.Lists["Document cv"];

            SPListItemCollection lstCol = myList.Items;


            foreach (SPListItem lstItem in lstCol)
            {

                var fileNames = lstItem.Attachments.Cast<string>().ToList();

                for (int i = 0; i < fileNames.Count; i++)
                {
                    var fileName = fileNames[i];
                    if (lstItem.Attachments.UrlPrefix + fileName == hp.NavigateUrl)
                    {
                        lstItem.Attachments.Delete(fileName);

                    }

                }
                lstItem.Update();

                lstItem.Delete(); 
            }


        }
    }
share|improve this question
    
its deleting the last item becuase your not looping through each checked item and performing the above! so what it does is the last item in the list as thats the last item that was checked ;) –  ali Sharepoint Apr 11 '13 at 8:26
    
@aliSharepoint Sharepoint se the updated code above should loop true here? –  Martin Apr 11 '13 at 8:29
    
@aliSharepoint the code the i last updated deletes multiple selected checkboxes from the database but now from the list only the last one –  Martin Apr 11 '13 at 8:31
    
@Martin - Your last code review still deletes only the last item? Also, please - do not shapeshift your question. We have no problem if you need more help and ADD a related question to the original one. Just please do not remove the original. Many answers do not make sense anymore if you remove a piece of the question. –  SPArchaeologist Apr 11 '13 at 9:00
    
@SPArchaeologist The differens with the old a new code is that i have added listItem.Recycle(); what does not make sense? i have updated. –  Martin Apr 11 '13 at 9:04
show 2 more comments

4 Answers

Is there any reason why your incrementing by 2 on i every time?

protected void ButtonDeleteAttachments_Click(object sender, EventArgs e)
{
    {
        for (int i = 0; i <= RepeaterDocument.Controls.Count + 1; i++)
        {
            if (RepeaterDocument.Controls[i + 1] is CheckBox)
            {
                CheckBox tmp = (CheckBox) RepeaterDocument.Controls[i];

                if (tmp.Checked)
                {
                    HyperLink hp = (HyperLink) RepeaterDocument.Controls[i + 1];

                    DeleteFromDb(hp);
                    DeleteFromSharePointList(hp);
                }
            }
        }
    }
}

You nee to put a break point at the start of the for loop and check each value to see if its correct!

eg RepeaterDocument.Controls.Count what is its total value? were you doing i += 2 which == 0,2,4,6,8 because you know the checkbox is exacly in that position every time? and you need the value to increament within an if statment? but you seem to be checking if its a checkbox anyway! so there is no need to do that! now go through the debugging and see when it hits:

                if (tmp.Checked)
                {
                    HyperLink hp = (HyperLink) RepeaterDocument.Controls[i + 1];

                    DeleteFromDb(hp);
                    DeleteFromSharePointList(hp);
                }

when you go through each for loop it will show you the result and why! plesae post back here to let me know! use my code that iv ammended slightly ;)

EDIT

ok ill explain your code and what i think!

protected void ButtonDeleteAttachments_Click(object sender, EventArgs e)
{
            //ok so you know exactly that each loop will be a checkbox!
            for (int i = 0; i < RepeaterDocument.Controls.Count; i += 2)
            {
                //as you know its a checkox there is no need for this but i 
                //dont belive this is the issue, you need to put a break point
                // here to see if it goes through or not when debugging!
                if (RepeaterDocument.Controls[i] is CheckBox)
                {
                    //ok so its a checkbox and you want to set the control into a 
                    //new checkbox. 
                    CheckBox tmp = (CheckBox) RepeaterDocument.Controls[i];

                    //now you need to check here! if its checked or not!! 
                    if (tmp.Checked)
                    {
                        HyperLink hp = (HyperLink) RepeaterDocument.Controls[i + 1];

                        DeleteFromDb(hp);
                        DeleteFromSharePointList(hp);
                    }
                }
            }
}

ok so this is my therory ;) if (tmp.Checked) this is the issue i belive! the first checkbox wich value is 0 I belive is not check, in simple terms that its value isnt passed but its checked on the client side! thats why im asking you to debug to that line to see the value of the first checkbox? im guessing that its only registering the last action (last check!)

EDIT

iv just ran into a similar problem where i want to delete a list item with the same id in multiple lists! The problem is with the foreach loop! the first iteration works but than the srcond fails and shows the same error! It has todo with .net and the fact that you cant loop read and delete within the same foreach or for loop, so you cant read the list and delete at the same time.... I presume that its the same for you aswell! you need to seperate the for loop method from the delete method!

the parts that you need to seperate is the foreach loop that your reading from the list and the method lstItem.Attachments.Delete(fileName); , save the fileName value in an array and loop through that instead witin a seperate delete function that gets called once the foreach loop has finished ;) !

share|improve this answer
    
i have two controls for every item in the repeater that why i use +=2 –  Martin Apr 11 '13 at 9:12
    
on 0 is checkbox, on 1 is hyperlink, and so an –  Martin Apr 11 '13 at 9:15
    
i have added 2 items every item has 2 controls for (int i = 0; i < RepeaterDocument.Controls.Count; i += 2) RepeaterDocument.Controls.Count; = 4 –  Martin Apr 11 '13 at 9:20
    
when i do like the post that u posted i get {"Specified argument was out of the range of valid values.\r\nParameter name: index"} on if (RepeaterDocument.Controls[i] is CheckBox) value=null on inneExeption it because it cant find the checkbox because it count false –  Martin Apr 11 '13 at 9:24
    
thats becasue i think of the control not starting at 0 but rather 1, so iv added the extra +1 to do the check against –  ali Sharepoint Apr 11 '13 at 9:33
show 2 more comments

You just need to use the Delete() method on the SPListItem instance.

private void DeleteFromSharePointList(HyperLink hp)
{

    SPWeb web = SPContext.Current.Web;
    web.AllowUnsafeUpdates = false;

    SPList myList = web.Lists["Document cv"];

    int docId = Convert.ToInt32(HiddenFieldID.Value);

    SPListItem listItem = myList.Items.GetItemById(docId);

    listItem.Delete();
}

Also notice that .Delete() will delete the item without sending it to the Recycle bin. If you want to move the item to the bin (so that you can still save it if you delete the wrong item) you need to use the .Recycle() method.


EDIT: about the second issue. You are looping on the checked items in the item list. Since you call DeleteFromDB and DeleteFromSharepoint one after another we can be sure that both are executed for each item. This means that the DeleteFromSharepoint method is called but doesn't delete the item.

In the method you are doing this:

int docId = Convert.ToInt32(HiddenFieldID.Value);
SPListItem listItem = myList.Items.GetItemById(docId);

You get the item to delete based on an hidden field value. I suspect that this is the problem: the hidden field value does non relate to the current processed checkbox or hyperlink.


EDIT2 About the code in the last version of the question. To simplify:

private void DeleteFromSharePointList(HyperLink hp)
{
    {
        SPWeb web = SPContext.Current.Web;
        web.AllowUnsafeUpdates = false;

        SPList myList = web.Lists["Document cv"];

        SPListItemCollection lstCol = myList.Items;


        foreach (SPListItem lstItem in lstCol)
        {
            lstItem.Delete(); 
        }

    }
}

basically, regardless of the specified hyperlink, you cycle on the whole collection of items and delete each one. Lucky since you are modifying the same collection you enumerate on, .Net will raise an error about the collection begin modified. Wasn't for that error, all of the list items would have been terminated. You need to delete only the item for the current attachment ID. Again, I don't know your code but you may be able to recover the item id from the attachment url. The url is in the format ListName/Attachments/ItemID/attachment - this means that you could extract the id from there.

share|improve this answer
    
@SPArchaelogist i get Item does not exist. It may have been deleted by another user. –  Martin Apr 11 '13 at 7:45
    
on my listItem.Update i get SPException was unhanhled by user code {"Item does not exist. It may have been deleted by another user."} –  Martin Apr 11 '13 at 7:49
    
@Martin - are you calling listItem.Update() after you called listitem.Delete()? Delete() deletes all info about the item (including its attachments) so after you call it, the item is gone. No need to perform other operation afterward. –  SPArchaeologist Apr 11 '13 at 8:37
    
In my answer I have replaced the part that deletes the attachments with a call to listItem.Delete(). Have you done the same of have you inserted the call to delete before the code used to delete the attachment? Again, Delete() deletes the whole item, so you cannot access it afterward. –  SPArchaeologist Apr 11 '13 at 8:39
    
You get the item to delete based on an hidden field value. I suspect that this is the problem: the hidden field value does non relate to the current processed checkbox or hyperlink. i also think so but if i dont use getitembyid how could i solve this doing the thing that i want to do? –  Martin Apr 11 '13 at 12:17
show 2 more comments

Take a look at this link: http://msdn.microsoft.com/en-us/library/ms467435(v=office.14).aspx

Or just add listItem.Delete();

Also you can use listItem.Recycle() to delete to the recycle bin.

share|improve this answer
    
i get Item does not exist. It may have been deleted by another user. when i use listItem.Delete(); because it dont now what to delete :P –  Martin Apr 11 '13 at 7:43
    
Probably you try to use Delete() and Update() after it? In such a case you will get this error. You don't need to do Update after deleting –  MikhailSP Apr 11 '13 at 7:52
    
i have removes listItem.Remove(); still get same error –  Martin Apr 11 '13 at 7:53
    
you don't need to use listItem.Recycle inside a cycle for. As inside a cycle it tries to delete the item several times. So you need to use listItem.Remove() right after you get listItem on SPListItem listItem = myList.Items.GetItemById(docId); –  MikhailSP Apr 11 '13 at 8:13
    
i solve it but se my next problem in the top –  Martin Apr 11 '13 at 8:16
add comment

Yeah, you're not going to be able to delete an item from a list that you're iterating through. This isn't a SharePoint issue so much as it is a C# issue. Luckily, there's a nice and easy workaround:

SPListItemCollection lstCol = myList.Items;
int listCount = lstCol.Count;

for(int i = 0; i < listCount; i++)
{
  if(insert logic here)
  {
     lstCol[i].delete();
  }
}

Hope that helps!

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.