For deleting a collection elements from a Revit model, one of the commonly used approaches is to use FilteredElementCollector and filter based on certain criteria like Category of the element. Now with the list of elements, developers often iterate through each element from this filtered list and check the name (say Family name) of the element/instance. If the name matches with the one that needs to be deleted, the element or instance is deleted using Document.Delete() method in the loop itself. This has often reported to cause unexpected behavior during or after the execution of the code.
The reason for this behavior is the deletion call during the iteration of elements itself. This is not a supported operation and should be avoided. And this is not specific to deletion based on any category or type (as you might have guessed it by now). The correct approach is to collect the desired elements using the Filters and then delete after completing the iteration. The following code demonstrates the suggested workflow for, say, deleting annotation families in a model with a specific Name:
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace Revit.SDK.Samples.HelloRevit.CS
{
[Transaction(TransactionMode.Manual)]
public class Command : IExternalCommand
{
public Result Execute(ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
UIApplication uiApp = commandData.Application;
Document doc = uiApp.ActiveUIDocument.Document;
FilteredElementCollector coll =
new FilteredElementCollector(doc).OfClass(typeof(Family));
IEnumerable<Element> elems =
from Family d in coll
where d.FamilyCategory.Name.Equals("Generic Annotations")
where d.Name.Equals("XYZ")
select d;
Family annFam = elems.First() as Family;
Transaction trans = new Transaction(doc, "Delete");
trans.Start();
doc.Delete(annFam);
trans.Commit();
return Result.Succeeded;
}
}
}