If this is your first time coding in Revit API, this post will outline most of the important details on Getting Started.
Alright, now that we have a good idea of where to get started, we can start writing some real code! Today we’re going to start with the first step to a real Revit add-in - buttons! There are a few key pieces, and we’ll address them each in their own sections below. We’re going to cover:
Creating an IExternalApplication
Creating a RibbonTab
Creating a RibbonPanel
Creating a PushButton
Adding Button’s Code-Behind
If you’re the type that likes to jump right into the code, you can find a link to our github at the bottom of this post.
Creating an IExternalApplication
Your IExternalApplication class is the entry point into your application - the class defined here is responsible for defining all of the ways that you intend to interact with Revit through your application.
This includes straightforward interactions, like buttons/commands that are triggered by a user clicking a button or using a keyboard shortcut. It also includes less straightforward interactions like event handlers, which are triggered by Revit when “something happens,” like the active view is changed or a new document (a Revit model) is created.
public class App : IExternalApplication { public Result OnStartup(UIControlledApplication application) { try { RibbonControl _ribbon = ComponentManager.Ribbon; string _tabName = "BIM 365"; RibbonTab _tab = Helpers.CreateTab( application, _ribbon, _tabName); string _helpPanelName = "Help"; Help.Panel.AddPanel(application, _tab, _helpPanelName); return Result.Succeeded; } catch (Exception _ex) { TaskDialog.Show("Error", _ex.Message + _ex.StackTrace); return Result.Failed; } } public Result OnShutdown(UIControlledApplication application) { //Handle any application clean-up here! return Result.Succeeded; } }
Creating a RibbonTab
Creating our Tab in the RibbonControl is perhaps the oddest bit of code we’ll need to write today. This is simply because Revit’s method to create a RibbonTab does not return the created RibbonTab. Further, it isn’t accessible via an ID - just the name that the tab was created under.
So it’s very important that you give your tab a unique name. Once that’s created, we want to find it and return it, so that we can add Panels and other things to it later.
internal static RibbonTab CreateTab( UIControlledApplication application, RibbonControl ribbon, string tabName) { try { application.CreateRibbonTab(tabName); RibbonTab _tab = null; foreach (RibbonTab _existingTab in ribbon.Tabs) { if (_existingTab.Id == tabName) { _tab = _existingTab; break; } } if (_tab == null) { throw new Exception("Could not create tab: " + tabName); } return _tab; } catch (System.Exception _ex) { throw _ex; } }
Creating a RibbonPanel
The RibbonPanel is what Revit uses to group buttons and other controls that our users will interact with. Creation here is pretty simple - just call the method and be sure to declare the result as a variable, so we can reference it later when adding buttons etc.
RibbonPanel _panel = uiControlledApplication.CreateRibbonPanel( ribbonTab.Name, panelName);
Creating a PushButton
Our last method interacting with the Ribbon is where we’ll add our button(s) and other user controls. All you need here is:
An ID (must be unique)
A Name (users will see this)
The assembly’s full name (the DLL file we’re working to build is the assembly)
The full name of the class for our command
The panel we’ll add the button to
DirectoryInfo _thisAssemblyDirectoryInfo = new DirectoryInfo( Assembly.GetExecutingAssembly().Location); //About Button PushButtonData _aboutButtonData = new PushButtonData( "BIM365_About", "About", _thisAssemblyDirectoryInfo.FullName, typeof(AboutCommand).FullName); _panel.AddItem(_aboutButtonData);
Adding Button’s Code-Behind
And here’s where we add in our functional code! This command is intentionally simple, and will open a link to our page, www.bim365.tech.
Notice that I use two methods - Execute and execute.
“Execute” is the entry point for the command, and is fired when a user clicks the button or uses a keyboard shortcut for the command. I like to separate this because it’s a great spot to standardize putting typical things like logging, authentication, or any setup interactions that aren’t Revit-specific.
“execute” is more of a control function - this is where all of the Revit stuff happens, and I recommend placing any transactions in this method, and this method only. If you choose to put your transactions elsewhere, all I can advise is to be consistent. The intent is to make bugs easy to find, and transactions easy to roll back if something goes wrong.
[Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] internal class AboutCommand : IExternalCommand { public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { return execute(commandData.Application.ActiveUIDocument); } private Result execute(UIDocument uiDoc) { try { System.Diagnostics.Process.Start( @"https://www.bim365.tech/"); return Result.Succeeded; } catch (Exception _ex) { TaskDialog.Show("Error", _ex.Message + _ex.StackTrace); return Result.Failed; } } }
ADDIN and DLL Files
Now that we have all of our code written, it’s time to build our Project and test it out! Here are the steps:
Build it (in Visual Studio, right click on the Project in the Solution Explorer. If everything was written correctly, your Output window should indicate “Build Successful.”
Locate your DLL File - it should be named to match your Project, and be located in one of the bin sub-folders.
Create your ADDIN File - this is what Revit uses to recognize that there is a DLL to load. You can find great details on what .ADDIN files are, and how to create one here.
Copy your DLL and ADDIN to either of these locations (paths may differ if you’re using a non-default installation location for Revit):
(for the current user only) C:\Users\<Username>\AppData\Roaming\Autodesk\Revit\Addins\<RevitYear>
(for any user on the machine): C:\ProgramData\Autodesk\Revit\Addins\<RevitYear>