Application: Revit API
Category: User Interface
Difficulty: Intermediate
Language: C#
You want to organize your add-in commands in a professional-looking custom ribbon panel instead of having them appear under the default "External Tools" section.
Implement an IExternalApplication class that creates a custom ribbon panel during Revit startup. This allows you to add buttons, split buttons, and stacked items with custom icons.
using System;
using System.Reflection;
using System.Windows.Media.Imaging;
using Autodesk.Revit.UI;
namespace MyRevitAddin
{
public class Application : IExternalApplication
{
public Result OnStartup(UIControlledApplication application)
{
try
{
// Create a custom ribbon panel
RibbonPanel panel = application.CreateRibbonPanel("My BIM Tools");
// Get the path to this assembly
string assemblyPath = Assembly.GetExecutingAssembly().Location;
// Create a push button
PushButtonData buttonData = new PushButtonData(
"MyCommand",
"Wall\nAnalyzer",
assemblyPath,
"MyRevitAddin.WallAnalyzerCommand");
PushButton button = panel.AddItem(buttonData) as PushButton;
button.ToolTip = "Analyze walls in the current project";
button.LongDescription = "This command collects all walls and provides " +
"detailed analysis including areas, volumes, and fire ratings.";
// Add icon (32x32 for large, 16x16 for small)
button.LargeImage = new BitmapImage(
new Uri("pack://application:,,,/MyRevitAddin;component/Resources/icon32.png"));
button.Image = new BitmapImage(
new Uri("pack://application:,,,/MyRevitAddin;component/Resources/icon16.png"));
return Result.Succeeded;
}
catch (Exception ex)
{
TaskDialog.Show("Startup Error", ex.Message);
return Result.Failed;
}
}
public Result OnShutdown(UIControlledApplication application)
{
// Cleanup code here if needed
return Result.Succeeded;
}
}
}
public void CreateStackedButtons(RibbonPanel panel, string assemblyPath)
{
// Create three button data objects
PushButtonData button1Data = new PushButtonData(
"Cmd1", "Button 1", assemblyPath, "MyRevitAddin.Command1");
PushButtonData button2Data = new PushButtonData(
"Cmd2", "Button 2", assemblyPath, "MyRevitAddin.Command2");
PushButtonData button3Data = new PushButtonData(
"Cmd3", "Button 3", assemblyPath, "MyRevitAddin.Command3");
// Add as stacked items (shows 3 buttons in one column)
panel.AddStackedItems(button1Data, button2Data, button3Data);
}
public void CreateSplitButton(RibbonPanel panel, string assemblyPath)
{
// Create split button
SplitButtonData splitButtonData = new SplitButtonData(
"SplitButton", "Analysis Tools");
SplitButton splitButton = panel.AddItem(splitButtonData) as SplitButton;
// Add buttons to the split button
PushButtonData option1 = new PushButtonData(
"Option1", "Wall Analysis", assemblyPath, "MyRevitAddin.WallAnalysis");
splitButton.AddPushButton(option1);
PushButtonData option2 = new PushButtonData(
"Option2", "Door Analysis", assemblyPath, "MyRevitAddin.DoorAnalysis");
splitButton.AddPushButton(option2);
PushButtonData option3 = new PushButtonData(
"Option3", "Room Analysis", assemblyPath, "MyRevitAddin.RoomAnalysis");
splitButton.AddPushButton(option3);
}
Update your .addin manifest to register the External Application:
<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
<AddIn Type="Application">
<Assembly>MyRevitAddin.dll</Assembly>
<ClientId>A1B2C3D4-E5F6-7890-ABCD-EF1234567890</ClientId>
<FullClassName>MyRevitAddin.Application</FullClassName>
<VendorId>MYCO</VendorId>
<VendorDescription>My Company Name</VendorDescription>
</AddIn>
</RevitAddIns>
\n in button text to create multi-line labelsMistake: Trying to access the document in OnStartup
// WRONG - no document is open yet
public Result OnStartup(UIControlledApplication application)
{
Document doc = application.ActiveUIDocument.Document; // Will fail!
}
// CORRECT - only create UI, don't access documents
public Result OnStartup(UIControlledApplication application)
{
RibbonPanel panel = application.CreateRibbonPanel("My Tools");
// Add buttons only, no document access
}
using System;
using System.Reflection;
using System.Windows.Media.Imaging;
using Autodesk.Revit.UI;
namespace MyRevitAddin
{
public class Application : IExternalApplication
{
public Result OnStartup(UIControlledApplication application)
{
try
{
// Create a custom ribbon panel
RibbonPanel panel = application.CreateRibbonPanel("My BIM Tools");
// Get the path to this assembly
string assemblyPath = Assembly.GetExecutingAssembly().Location;
// Create a push button
PushButtonData buttonData = new PushButtonData(
"MyCommand",
"Wall\nAnalyzer",
assemblyPath,
"MyRevitAddin.WallAnalyzerCommand");
PushButton button = panel.AddItem(buttonData) as PushButton;
button.ToolTip = "Analyze walls in the current project";
button.LongDescription = "This command collects all walls and provides " +
"detailed analysis including areas, volumes, and fire ratings.";
// Add icon (32x32 for large, 16x16 for small)
button.LargeImage = new BitmapImage(
new Uri("pack://application:,,,/MyRevitAddin;component/Resources/icon32.png"));
button.Image = new BitmapImage(
new Uri("pack://application:,,,/MyRevitAddin;component/Resources/icon16.png"));
return Result.Succeeded;
}
catch (Exception ex)
{
TaskDialog.Show("Startup Error", ex.Message);
return Result.Failed;
}
}
public Result OnShutdown(UIControlledApplication application)
{
// Cleanup code here if needed
return Result.Succeeded;
}
}
}