When working in Revit, copied elements will inherit instance parameter values that should be unique—room numbers, tracking codes, asset IDs, or any other metadata that doesn’t logically carry over.
Problem: Copying elements can introduce data inconsistencies if certain instance parameters retain values they shouldn’t.
Solution: A Revit API Updater that automatically clears specific parameters whenever elements are copied.
This tutorial will walk you through:
✅ How the Updater Works
✅ Setting Up the Revit Ribbon UI (Enable/Disable Feature)
✅ Registering the Updater
✅ Code Implementation
✅ How to Extend the Tool for Your Own Needs
How the Revit Updater Works
The Updater leverages Revit’s Dynamic Model Update (DMU) API, which allows you to react to changes in the model:
- Detects when elements are copied or added
- Checks if the copied element contains the specified parameter
- Automatically clears the parameter value
Why Use This?
- Prevents copied elements from inheriting unique metadata
- Reduces errors in schedules and exported data
- Ensures compliance with data integrity requirements
Step 1: Setting Up the Revit Ribbon UI
To provide better user control, this tool includes a simple Revit Ribbon UI that allows users to toggle the updater on or off.
How the UI Works
Activate button – Enables the updater
Deactivate button – Disables the updater
Placed inside a custom Revit tab: “Updater Tool”
- Activate button – Enables the updater
- Deactivate button – Disables the updater
- Placed inside a custom Revit tab: “Updater Tool”
Code: Creating the Revit UI (ExternalProgram.cs)
Click to expand and see the code
using System;
using System.IO;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Windows.Media.Imaging;
namespace UpdaterTool
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class ExternalProgram : IExternalApplication
{
public Result OnStartup(UIControlledApplication application)
{
application.CreateRibbonTab("Updater Tool");
string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string dllPath = Path.Combine(appData, @"Autodesk\REVIT\Addins\2023\UpdaterTool.dll");
string appFolderPath = Path.Combine(appData, @"Autodesk\REVIT\Addins\2023");
RibbonPanel ribbonPanel = application.CreateRibbonPanel("Updater Tool", "Updater");
RadioButtonGroupData radioButtonGroupData1 = new RadioButtonGroupData("radioButtonGroup1");
RadioButtonGroup radioButtonGroup1 = ribbonPanel.AddItem(radioButtonGroupData1) as RadioButtonGroup;
ToggleButtonData toggleButton1 = new ToggleButtonData("toggleButton1", "Deactivate", dllPath, "UpdaterTool.Deactivated");
toggleButton1.LargeImage = new BitmapImage(new Uri(Path.Combine(appFolderPath, "Stop.png")));
ToggleButtonData toggleButton2 = new ToggleButtonData("toggleButton2", "Activate", dllPath, "UpdaterTool.Activated");
toggleButton2.LargeImage = new BitmapImage(new Uri(Path.Combine(appFolderPath, "Check.png")));
radioButtonGroup1.AddItem(toggleButton1);
radioButtonGroup1.AddItem(toggleButton2);
return Result.Succeeded;
}
public Result OnShutdown(UIControlledApplication application)
{
return Result.Succeeded;
}
}
}
Code language: C# (cs)Step 2: Registering the Updater
To enable the updater, we register it inside a separate command class (InternalProgram.cs).
Code: Activating & Deactivating the Updater
Click to expand and see the code
using System;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;
namespace UpdaterTool
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
class Activated : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIApplication uiapp = commandData.Application;
AddInId addInId = uiapp.ActiveAddInId;
UpdaterClass updater = new UpdaterClass(addInId);
UpdaterId updaterId = updater.GetUpdaterId();
if (!UpdaterRegistry.IsUpdaterRegistered(updaterId))
{
UpdaterRegistry.RegisterUpdater(updater);
UpdaterRegistry.EnableUpdater(updaterId);
TaskDialog.Show("Updater", "Updater Activated!");
}
else
{
TaskDialog.Show("Updater", "Updater is already active.");
}
return Result.Succeeded;
}
}
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
class Deactivated : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIApplication uiapp = commandData.Application;
AddInId addInId = uiapp.ActiveAddInId;
UpdaterClass updater = new UpdaterClass(addInId);
UpdaterId updaterId = updater.GetUpdaterId();
if (UpdaterRegistry.IsUpdaterRegistered(updaterId))
{
UpdaterRegistry.RemoveAllTriggers(updaterId);
UpdaterRegistry.DisableUpdater(updaterId);
UpdaterRegistry.UnregisterUpdater(updaterId);
TaskDialog.Show("Updater", "Updater Deactivated!");
}
else
{
TaskDialog.Show("Updater", "Updater was not active.");
}
return Result.Succeeded;
}
}
}
Code language: C# (cs)Step 3: The Updater Logic
The core functionality of this tool is inside UpdaterClass.cs.
- Listens for new elements being added (including copied elements)
- If the new element has the target parameter, it clears the value
Listens for new elements being added (including copied elements)
If the new element has the target parameter, it clears the value
Code: UpdaterClass.cs
Click to expand and see the code
using System;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace UpdaterTool
{
class UpdaterClass : IUpdater
{
private static AddInId addInId;
private static UpdaterId updaterId;
public UpdaterClass(AddInId addInId)
{
UpdaterClass.addInId = addInId;
updaterId = new UpdaterId(UpdaterClass.addInId, new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
}
public void Execute(UpdaterData data)
{
Document doc = data.GetDocument();
using (SubTransaction str = new SubTransaction(doc))
{
try
{
str.Start();
var addedElementIds = data.GetAddedElementIds();
foreach (ElementId id in addedElementIds)
{
Element element = doc.GetElement(id);
if (element == null) continue;
Parameter param = element.LookupParameter("YourParameterNameHere");
if (param != null && !param.IsReadOnly)
{
param.Set(""); // Clears the copied parameter
}
}
str.Commit();
}
catch
{
str.RollBack();
}
}
}
public UpdaterId GetUpdaterId() => updaterId;
public ChangePriority GetChangePriority() => ChangePriority.FreeStandingComponents;
public string GetUpdaterName() => "Custom Parameter Updater";
public string GetAdditionalInformation() => "Clears a specific parameter when elements are copied.";
}
}
Code language: C# (cs)Summary
✅ Created a Revit Updater that listens for copied elements
✅ Clears specified instance parameters to prevent unintended metadata retention
✅ Included a Revit UI toggle to enable or disable the updater
How Can You Extend This?
- Modify the parameter name to suit your project needs
- Expand functionality to reset multiple parameters
- Add logging to track when elements are modified



No Comments