Sometimes in order to create, you have to destroy

To follow up with another post about directionality, I wanted to first introduce the important concept of using the Delete method for things other than deleting objects.

One of the valuable applications is when we want to find the doors or windows in a wall. For any given hosted family instance we can use the FamilyInstance.Host property to find the wall that hosts it.

But what if we want to go the other way, and start with a wall and find the elements hosted by it? A great way to do this is delete the wall and get the data that Revit provides about all items that were deleted (because deleting the wall also deletes its doors & windows).

But wait! You just messed up my model by deleting a wall!

No, not really. This deletion of the wall does will not be committed to the Revit model and we can still get the info we want. By using Transaction.Rollback (instead of Transaction.Commit) the wall was never really deleted.

Here’s an example that finds the doors in the selected wall. For the screenshot I selected the horizontal wall, and the dialog box shows only the doors in that wall (note that the double door in the vertical wall is not listed).

doors in wall

public void FindDoorsInWall()
{
    Document doc = this.ActiveUIDocument.Document;
    UIDocument uidoc = new UIDocument(doc);
    Wall wall = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element)) as Wall;
    List<ElementId> wallAndChildren = new List<ElementId>();
    using( Transaction transaction = new Transaction(doc,"Delete Wall") )
    {
      transaction.Start();
      wallAndChildren = doc.Delete(wall) as List<ElementId>;
      // roll back the tranaction instead of using transaction.Commit()
      // we don't really want to delete the wall
      transaction.RollBack();
    }
    string doors = "";
    foreach (ElementId id in wallAndChildren)
    {
        FamilyInstance famInst = doc.GetElement(id) as FamilyInstance;
        if (famInst != null && famInst.Category.Name == "Doors")
        // need this check to exclude the wall that was deleted
        // the check for null determines that the element is a FamilyInstance					
        {
            FamilySymbol familySymbol = famInst.Symbol;
            Family family = familySymbol.Family;
            doors += family.Name + " - " + famInst.Name + "\n";
        }
    }
    TaskDialog.Show("doors in selected wall", doors);
}
Advertisements

4 thoughts on “Sometimes in order to create, you have to destroy

  1. I spent a whole day trying to find some code to read doors information out of a wall without success. Your posts are so good I couldn’t believe i am so lucky to find it (through a link on ‘better Revit’). Thank you! and looking forward your future posts.

  2. WOW!! impressive post indeed!… but i have a question: what makes the statment ” wallAndChildren = doc.Delete(wall) as List;” report the deleted hosted objects such as doors as well as the deleted wall, while you only asked to delete wall. what makes it sense the others elements!!!

    • Document.Delete returns the collection of elements that were deleted. If you delete a wall and that results in the deletion of the wall, doors, and windows, the Delete method returns the deleted wall, doors, and windows.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s