Over at Revit SWAT there is a great post about how to modify a wall-hosted family so it gives an alert when the host wall is too thin. This topic is a great excuse for me to write about Dynamic Model Update, the Revit API feature that automatically runs API code when your Revit model changes.
The idea in this example is to alert the user when a toilet is placed on a wall that is too thin to hold its plumbing. To do this, we need to have API code that runs automatically when the model changes.
But before coding such a real-time alert, here is a quick sample showing how to check all plumbing fixtures that are already in the model.
public void checkPlumbingWallWidth()
{
Document doc = this.ActiveUIDocument.Document;
string tooThin = "";
SelElementSet selSet = SelElementSet.Create();
foreach (FamilyInstance inst in (from i in new FilteredElementCollector(doc)
.OfClass(typeof(FamilyInstance)) // find only FamilyInstances
.OfCategory(BuiltInCategory.OST_PlumbingFixtures) // find only Plumbing Fixtures
.Cast<FamilyInstance>() // cast to FamilyInstance so FamilyInstance.Host can be used
where ((Wall)i.Host).Width < 0.5 // FamilyInstance.Host returns an Element, so cast it to a Wall so Wall.Width can be used
select i))
{
tooThin += inst.Symbol.Family.Name + ", id = " + inst.Id + "\n";
selSet.Add(inst); // add the instance to the selection set
}
UIDocument uidoc = new UIDocument(doc);
uidoc.Selection.Elements = selSet;
uidoc.RefreshActiveView();
TaskDialog.Show("Plumbing in Walls < 6\"",tooThin);
}

For more info on the SelElementSet functionality to select the elements that are found, see https://boostyourbim.wordpress.com/2012/12/15/retrieving-and-selecting-elements-in-a-selectionfilterelement/
Now for the real-time alert!
With the code below, placing the toilet on the vertical (thicker) wall gives no warning. But placing one on the thin horizontal wall gives the warning shown.

Below is the code for 3 macros:
- FamilyInstanceUpdater – the code that runs when the trigger occurs
- RegisterUpdater to turn on the updater
- UnregisterUpdater to turn off the updater
public class FamilyInstanceUpdater : IUpdater
{
static AddInId m_appId;
static UpdaterId m_updaterId;
// constructor takes the AddInId for the add-in associated with this updater
public FamilyInstanceUpdater(AddInId id)
{
m_appId = id;
// every Updater must have a unique ID
m_updaterId = new UpdaterId(m_appId, new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
}
public void Execute(UpdaterData data)
{
Document doc = data.GetDocument();
// loop through the list of added elements
foreach (ElementId addedElemId in data.GetAddedElementIds())
{
// check if the added element is a family instance of the Plumbing Fixtures category
FamilyInstance instance = doc.GetElement(addedElemId) as FamilyInstance;
if (instance != null && instance.Category.Name == "Plumbing Fixtures")
{
// Get the instance's host wall
Wall wall = instance.Host as Wall;
// Check that there is a host wall and that its width is greater than 6"
// Revit API uses feet for distance measurements
if (wall != null && wall.Width < 0.5)
TaskDialog.Show("Warning!", "Your wall is too thin!");
}
}
}
public string GetAdditionalInformation(){return "Family Instance host wall thickness check";}
public ChangePriority GetChangePriority(){return ChangePriority.FloorsRoofsStructuralWalls;}
public UpdaterId GetUpdaterId(){return m_updaterId;}
public string GetUpdaterName(){return "Wall Thickness Check";}
}
// This command must be run to register the updater with Revit
// Often this is done as part of the Revit start-up process so that the updater is always active
public void RegisterUpdater()
{
FamilyInstanceUpdater updater = new FamilyInstanceUpdater(this.Application.ActiveAddInId);
UpdaterRegistry.RegisterUpdater(updater);
// Trigger will occur only for FamilyInstance elements
ElementClassFilter familyInstanceFilter = new ElementClassFilter(typeof(FamilyInstance));
// GetChangeTypeElementAddition specifies that the triggger will occur when elements are added
// Other options are GetChangeTypeAny, GetChangeTypeElementDeletion, GetChangeTypeGeometry, GetChangeTypeParameter
UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), familyInstanceFilter, Element.GetChangeTypeElementAddition());
}
public void UnregisterUpdater()
{
FamilyInstanceUpdater updater = new FamilyInstanceUpdater(this.Application.ActiveAddInId);
UpdaterRegistry.UnregisterUpdater(updater.GetUpdaterId());
}
I’ve tried to put a decent amount of description in the comments, for more info check out http://wikihelp.autodesk.com/Revit/enu/2013/Help/00006-API_Developer’s_Guide/0135-Advanced135/0152-Dynamic_152
Enhancement Idea:
- Create a trigger that uses GetChangeTypeGeometry instead of GetChangeTypeElementAddition with a filter for Walls. If an existing wall that is hosting toilets becomes thinner (because its structure is changed or the wall type is changed) then the warning should be given.
Like this:
Like Loading...