Custom Errors – Preventing Specific Changes to the Revit model

Let’s say there is a specific list of View Scales that you want allowed in your Revit projects. Or certain naming conventions that should be used. Or something else like that where you’d like to automate the process of checking a user’s change and determining if it should be allowed, prevented, or trigger a warning.

This can be done with two pieces of Revit API functionality – Updater & Custom Failures. You can find all the code here and an explanation in the video below.

If you think lessons like there are interesting and helpful, please support Boost Your BIM at Patreon, take one of our video courses on the Revit API, or contact us to discuss how we can work together to make Revit better.

            Utils.ViewScaleUpdater viewScaleUpdater = new Utils.ViewScaleUpdater(application.ActiveAddInId);
            UpdaterRegistry.RegisterUpdater(viewScaleUpdater, true);
            UpdaterRegistry.AddTrigger(
                viewScaleUpdater.GetUpdaterId(),
                new ElementClassFilter(typeof(View)),
                Element.GetChangeTypeParameter(new ElementId(BuiltInParameter.VIEW_SCALE)));

            Utils.illegalViewRangeFailureId = new FailureDefinitionId(Guid.NewGuid());
            FailureDefinition.CreateFailureDefinition(
                Utils.illegalViewRangeFailureId,
                FailureSeverity.Error,
                "This view scale is not allowed.");

A better Select By Type tool

There are a few things you can’t do with Revit’s “Select All Instances” tool

  • You can’t select all instance of one type and then all instances of another type and combine them into a single selection set
  • You can’t select lines
  • You can’t restrict the selection to all instances in the active view

To solve these limitations, try the new FREE Select By Type tool in the Boost Your BIM Terrific Tools.
If you enjoy using this and the other free tools and educational resources from Boost Your BIM, drop us a line and let us know how you’d like to make Revit better and support our work on Patreon.

Sometimes it’s not you

Here’s a really simple bit of code to create a wall and change the wall type

public void crash()
{
	Document doc = this.ActiveUIDocument.Document;
	WallType wt = new FilteredElementCollector(doc)
		.OfClass(typeof(WallType))
		.Cast<WallType>()
		.FirstOrDefault(q => q.Kind == WallKind.Basic);
	
	using (Transaction t = new Transaction(doc, "test"))
	{
		t.Start();
		Wall wall = Wall.Create(doc, 
            Line.CreateBound(XYZ.Zero, XYZ.BasisX),
            new FilteredElementCollector(doc).OfClass(typeof(Level)).FirstOrDefault().Id,
            false);		
		wall.ChangeTypeId(wt.Id);
		t.Commit();
	}
}

The problem is that when you create a wall with the Revit API, Revit uses the wall type last used when a wall was created with the user interface. If the last wall type used was a basic wall, then everything is fine. But if the last wall type used in the interface was a Curtain Wall…

You can work around this by adding a Document.Regenerate() just before changing the wall type. But it is a good reminder to think about how Revit’s state can affect your add-in, be careful working in the API with newly created elements, and that sometimes by adding a “regenerate” or changing how you are using transactions you can find a solution.