🏗️ Revit APIintermediateUI Development

Create Custom Ribbon Panel in Revit

Step-by-step guide to creating custom ribbon panels and buttons in Revit add-ins for better user experience.

1 views12/14/2025

Create Custom Ribbon Panels in Revit

Application: Revit API
Category: User Interface
Difficulty: Intermediate
Language: C#

Problem

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.

Solution

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.

Code Example

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;
        }
    }
}

Advanced: Creating Stacked Buttons

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);
}

Advanced: Creating Split Button with Dropdown

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);
}

Manifest File Configuration

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>

Icon Guidelines

  • Large icons: 32x32 pixels, PNG format with transparency
  • Small icons: 16x16 pixels, PNG format with transparency
  • Use simple, clear designs that work well at small sizes
  • Follow Autodesk's icon design guidelines for consistency
  • Set Build Action to "Embedded Resource" in Visual Studio

Key Points

  • External Applications load when Revit starts, not on-demand like External Commands
  • OnStartup runs before any document is opened
  • Use \n in button text to create multi-line labels
  • ToolTip shows on hover, LongDescription shows in extended tooltip
  • Panel names must be unique across all loaded add-ins

Common Pitfalls

Mistake: 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
}

Related Topics

  • External Application vs External Command
  • Ribbon panel organization
  • Context-sensitive button availability
  • Custom icons and branding

Code Example

C#
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;
        }
    }
}