BIM · Revit API · C#
Introducción completa a la API de Revit con C#
Base sólida para crear complementos profesionales: arquitectura, ciclo de vida, transacciones, filtros, parámetros, geometría y flujo de trabajo.
Mapa rápido de conceptos
| Área | Clase/Patrón | Nota |
|---|---|---|
| Acceso | UIApplication, UIDocument, Document |
Puente UI → modelo, documento activo y transacciones. |
| Transacciones | Transaction, SubTransaction, TransactionGroup |
Modificar modelo solo dentro de transacciones. |
| Búsqueda | FilteredElementCollector, ElementCategoryFilter |
Filtrado eficiente por categoría, clase, parámetros. |
| Parámetros | Parameter, BuiltInParameter, ParameterElement |
Leer/escribir conociendo StorageType. |
| Geometría | Options, GeometryElement, Solid, Face |
Controlar ComputeReferences y DetailLevel. |
| Vistas | View, ViewPlan, ViewSheet |
Crear, configurar y colocar en planos. |
Arranque del desarrollo
Un complemento básico se compone de una clase que implementa IExternalCommand (acción manual) o
IExternalApplication (ciclo de vida de la app: OnStartup/OnShutdown), más su archivo
.addin en la carpeta de Addins de Revit.
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class HelloCommand : IExternalCommand
{
public Result Execute(ExternalCommandData data, ref string msg, ElementSet set)
{
UIDocument uiDoc = data.Application.ActiveUIDocument;
Document doc = uiDoc.Document;
TaskDialog.Show("Hello", $"Documento: {doc.Title}");
return Result.Succeeded;
}
}
- Usa .NET 8 o .NET Framework 4.8.1 según la versión de Revit objetivo.
- Estructura recomendada: Core (lógica), UI (WPF), Services (Revit utils), Infrastructure (IO, config).
- Distribución: firma Authenticode opcional + ZIP con DLL, .addin y dependencias.
Arquitectura mínima y ciclo de vida
En IExternalApplication registra paneles y botones de la Ribbon, suscriptores a eventos y servicios
de inicio. En comandos, mantén clases delgadas que deleguen en servicios probables (p. ej. ViewService,
FilterService, ParameterService).
public class App : IExternalApplication
{
public Result OnStartup(UIControlledApplication a)
{
// Crear pestaña, panel y botón
return Result.Succeeded;
}
public Result OnShutdown(UIControlledApplication a) => Result.Succeeded;
}
Transacciones: reglas de oro
- Solo modifica el modelo dentro de
Transaction. - Valida y agrupa con
TransactionGroup; usaSubTransactionpara operaciones parciales. - En WPF usa ExternalEvent para invocar cambios desde el hilo UI de Revit.
using (var t = new Transaction(doc, "Crear nivel"))
{
t.Start();
Level lvl = Level.Create(doc, 0.0);
lvl.Name = "NIVEL 00";
t.Commit();
}
Búsqueda de elementos con FilteredElementCollector
La ruta eficiente: delimitar por vista o documento, filtrar por clase/categoría, y luego por parámetros.
var walls = new FilteredElementCollector(doc)
.OfClass(typeof(Wall))
.WhereElementIsNotElementType()
.Cast<Wall>()
.ToList();
var conParametro = walls.Where(w => w.LookupParameter("Comentarios")?.AsString()?.Contains("EJE") == true);
Parámetros: lectura/escritura segura
- Identifica BuiltInParameter cuando exista; es más robusto que el nombre.
- Lee StorageType para convertir correctamente:
Integer,Double,String,ElementId. - Respeta IsReadOnly y el contexto (tipo/instancia).
Parameter p = elem.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS);
if (p != null && !p.IsReadOnly && p.StorageType == StorageType.String)
{
using (var t = new Transaction(doc, "Escribir parámetro"))
{
t.Start();
p.Set("Texto de ejemplo");
t.Commit();
}
}
Familias y Tipos
Para crear/duplicar tipos usa ElementType.Duplicate; para cargar familias usa LoadFamily.
FamilySymbol sym = new FilteredElementCollector(doc)
.OfClass(typeof(FamilySymbol))
.Cast<FamilySymbol>()
.First(s => s.FamilyName == "MiFamilia" && s.Name == "Tipo A");
if (!sym.IsActive)
{
using (var t = new Transaction(doc, "Activar símbolo"))
{ t.Start(); sym.Activate(); t.Commit(); }
}
Geometría
Usa Options para controlar el nivel de detalle, referencias y manejo de vínculos.
Options opt = new Options { ComputeReferences = true, DetailLevel = ViewDetailLevel.Fine };
GeometryElement geo = elem.get_Geometry(opt);
foreach (GeometryObject g in geo)
{
if (g is Solid s && s.Volume > 1e-9) { /* ... */ }
}
Vistas y Planos
- Crear vista:
ViewPlan.CreateconLevelIdyViewFamilyType. - Crear plano:
ViewSheet.Createy colocar vistas conViewport.Create.
ViewSheet sheet;
using (var t = new Transaction(doc, "Plano"))
{
t.Start();
sheet = ViewSheet.Create(doc, ElementId.InvalidElementId);
sheet.Name = "COORDINACIÓN";
t.Commit();
}
UI, Selección y WPF
Para seleccionar: UIDocument.Selection.PickObject(s). Para WPF: usa ExternalEvent para
ejecutar cambios en el documento desde la ventana.
Eventos
Útiles: Application.DocumentOpened, ViewActivated, FailuresProcessing.
Maneja el performance: desuscríbete cuando no los uses.
Manejo de fallos (Failures)
Implementa IFailuresPreprocessor para interceptar avisos/errores y decidir continuar o abortar.
Rendimiento y buenas prácticas
- Minimiza colecciones globales: trabaja por lotes y por vista.
- Evita transacciones por elemento; agrupa operaciones.
- Usa Id y BuiltInParameter para referencias estables.
- Loguea tiempos y errores; agrega try/catch con mensajes claros.
Versionado y compatibilidad
Mantén proyectos por versión de Revit. Compila con los RevitAPI.dll de la versión objetivo y ajusta TargetFramework. Considera multi-targeting y directivas de compilación.
Recursos y siguientes pasos
- SDK de Revit (samples): imprescindible para patrones correctos.
- Foros de Autodesk, The Building Coder, GitHub de la comunidad.
- Ejercicios: crear una herramienta de filtros, exportar parámetros, generar planos.