image by archi-lab

create your own tab and buttons in revit

image by archi-lab

In the last few posts I have outlined in great detail how to make a simple Revit Add-in using the IExternalCommand implementation. Doing that is a great and really fast way of adding new tools to Revit, but after a while we will realize that we just need a little more organization. Luckily for us Revit API offers a way to create our own tab in Revit and an array of different ways to add buttons to it. For the sake of keeping this tutorial simple and easy to follow, I will only show you how to convert our all-ready CurveTotalLength tool to a button.

In this post we will cover a few things like:

  • IExternalApplication implementation
  • new RibbonPanel
  • new PushButton
  • resource management

First let’s open our Visual Studio session that we worked on last week. It should look like this:


On the right hand side, in our Solution Explorer I will first change the name of the CurveTotalLength cs file from Class1.cs to CurveTotalLength.cs.


  1. Right click on Class1.cs
  2. Click on Rename and type in “CurveTotalLength.cs”

Now, let’s just “Build it” and we can close that file.

This was just a quick maintenance procedure to make sure that our file is named properly because next what we will do is import that file into a new Project in Visual Studio. Unfortunately there isn’t an easy way to just take an existing project in Visual Studio and rename it. The easiest way is to actually just create a new project and add an existing one to it if needed. At least that’s what I have been doing.

So let’s create a new project in Visual Studio. This step was described before here. We will call it GrimshawRibbon, but you can call it whatever you want – just remember that it’s not easy to rename the project folder structure after it was created.

Next, just like we discussed before we need to reference in Revit API and Revit APIUI libraries. Again, look at this link here.

Now, let’s just quickly rename the default Class1.cs to App.cs like so(see image above):


Click Yes, to confirm.

Next, let’s add our existing CurveTotalLength project to this solution (SHIFT + ALT + A). When the window pops up we need to navigate to our CurveTotalLength project location and look for CurveTotalLength.cs file. You should see a new file appear in your Solution Explorer like so:


Next let’s quickly add a new folder to our project and then move(drag and drop) the CurveTotalLength to that folder to keep our application nicely organized:

  1. Right click on our project.
  2. Hover over Add…
  3. Click on New Folder

Before we start implementing the IExternalApplication, we need to make sure that we have all of the “using” statements as well as one more assembly loaded (PresentationCore), that we will need to define an icon/image for our button.


  1. Right click on References in Solution Explorer, then click on Add Reference…


  1. Click on “Assemblies” on the left side.
  2. In search field type in “Presentation”.
  3. Select PresentationCore from the list.
  4. Click OK.

Now, that we have all of the assemblies needed*, we can get to implementing IExternalApplication. First let’s create a “road map” using pseudo code before we start filling in the blanks:

*You will notice that we also defined using System.Reflection in code below. System is loaded in by default so there was no need to add it in, and all we needed to do was just type “using System.Reflection” to start using methods defined in that assembly.

This is a basic outline for our method. We haven’t done any heavy lifting yet, but we have a good idea about what needs to be done. We already loaded in PresentationCore and I mentioned that we will need it to define an image for our button. Before we get to code and explain how to define that image, let’s create the image and load it into our project first: I usually make my images roughly 320 x 320 pixels. That’s too big for the icon (32 x 32), but it’s much easier to work with that in Illustrator or Photoshop. Save your image to PNG (with transparency) and then you can easily create a 32px icon version of the file using online service called ICO Converter. For a single push button, we need a 32 pixel image so these settings will be fine: image09

  1. Select a PNG file.
  2. Select pixel size needed
  3. Select Bit Depth
  4. Click Convert

Files will be automatically saved in our Downloads folder and will be called favicon.ico so all we need to do is rename that file to totalLength.png. You will be prompted if you want to change the file extension to PNG so please click yes to confirm. Now, let’s add it into our Visual Studio project. First create a new folder in our Solution Explorer and call it “Resources” then add our file like so:


  1. Right click on Resources folder
  2. Hover over Add
  3. Click on Existing Item…

 Now we just need to navigate to the image that we want to use as our icon and select it. Once the image is inserted we need to change its BuildAction: image10

  1. Select our image in the Solution Explorer
  2. Change Build Action to Resource

Our image is ready, so are all of the assemblies needed, so we can go ahead and define our method that will create the tab and a new button:

Let’s go over it line by line:

  1. This defines what kind of method we want to create. For our purpose a “static”, “void” method will suffice. Static means that we are creating a method that can be invoked without first creating an instance of its parent class. Void means that our method will not return anything.
  2. .
  3. .
  4. This will be the name displayed on our tab.
  5. Here we create an instance of a new tab with the given name.
  6. .
  7. .
  8. Here we create a new Panel which will be added to our Tab. We call this panel Tools.
  9. .
  10. .
  11. Here we use Reflection method called Assembly to get a path to folder that our application is being compiled to.
  12. .
  13. .
  14. Before we create a new PushButton we need to create a PushButtonData instance
  15. first input is a unique name/id for our new button
  16. this is text that will be displayed under our button. I wanted our name to be two lines hence the System.Environment.NewLine piece of code.
  17. this is a location of a dll that will be called when button is pushed
  18. this is the name of the method that will be called including a namespace.
  19. .
  20. Here we add the new PushButton to our Panel.
  21. Here we define a tooltip message that will be displayed when user hovers over our button.
  22. Here we define a BitmapImage from the source. Bear in mind that it has to be defined as a URI source so we are creating a new instance of URI like so: new Uri(pack://application:,,,/GrimshawRibbon;component/Resources/totalLength.pngwhere “GrimshawRibbon” is the name of our current project followed by “;component” and then a “/Resources” which is the name of the folder we put our image into, then finally “/totalLength.png” which is the name of the file itself.
  23. Here we set the LargeImage property of the button to our image.
  24. .

This is really the gist of our application. Just to make sure that it all makes sense here’s where our variable are coming from:


Now that we have a method defined that will create the tab, all we have to do is call it when our plug-in is loaded into Revit – every time Revit starts. Here’s the full code:

The last step before we can fire up Revit is making sure that we have a addin manifest file that will register our application with Revit. Just like we did in the previous tutorial let’s just add a new TextFile to our project and call it GrimshawRibbon.addin. You can reference the steps from here. Here’s the code for this addin file (it differs slightly from an ExternalCommand registration):

Make sure that you are changing the addin file Build Action to Content and its Copy to Output Directory to Copy if newer.

Now, if we build our project we should have two files, that we can copy to our Revit addins location. Again, if you don’t know where that is, please reference previous tutorials here. Truth is that you should really read the previous three tutorials before attempting this one. :-)

Now, if you fire up Revit, you will have something like this:


Adding your own tab will probably make you realize that having a whole new tab just for one tool is kind of meaningless and you will set out on the path to fill it up with things that will make your life as a Revit user that much more easier. I have been doing this for a few months now, but I am up to 15 custom tools that I created for our office. Some are really simple like the one we were working with during this tutorial series, and some are a little bit more involved. Either way, having your own toolbar in your favorite application will for sure give you at least a small reason to be proud of yourself.

Thanks for sticking it out with me. It has been a long tutorial, lots of steps involved, but if you got through then its all it matters. Also, if I have missed anything – forgot to post an important image, skipped an important step – please let me know.

You can download the final DLL files from here:

GrimshawDT - GrimshawRibbon2016 (245 downloads)


  1. Brian Nickel says:

    Absolutely enjoy these posts Konrad. It’s about time someone explains the process in a easy to follow way! Kudos!

  2. Daniel Viero says:


    I’ve been struggling months trying to figure out a proper way to include my macros in an organized panel within the ribbon. Thanks a lot and congrats for the amazing job.

  3. Adam Smith says:

    Hi Konrad!
    Great post, thank you!
    For Revit 2016 it work like a charm, but when I’ve tested it for Revit 2014 it doesn’t work.
    Have you any advice how apopt it for Revit 2014?

    • Adam,

      Yes, I would recommend going to Start>Control Panel> Programs> Revit 2014 and hitting that Uninstall button on top of the window. :-) After the initial shock and nostalgia passes, believe me, life is better in year 2016 AD. But, seriously I can’t help you here. I refuse to provide backwards compatibility and localization issues help. I know, I am a horrible person. I will burn in hell, but at least it will be a modern one. Peace!

  4. Adam Smith says:

    Konrad, you make me laugh!
    I’m totally agree with you, but unfortunately, those who are creating content for Revit MEP are forced to use Revit 2014 or even worse Revit 2012 to insure backward compatibility. That’s why I was looking for a solution at least for Revit 2014.
    Nonetheless, thank you for your reply!

    • Adam, first thing that I would check is to make sure that you are referencing in RevitAPI and RevitAPIUI dlls from the 2014 location. Then try and compile. If everything works then you won’t have to anything else. If however, it doesn’t compile because I used some methods that were added to Revit API post 2014 version (I am not sure if I did, since I never built this particular plug-in for older versions) then you will have to replace them with their older versions, or it might not even be possible. I can’t tell because I never tried it myself.

      Good luck!

  5. Adam says:

    Konrad – thanks for the great tutorial, I was able to get my first button and got it to work great, what I am struggling with is adding a second button. I’m trying to add the Legend Duplicator and I keep getting a lot of errors when I copy the Push Button Data section and try to add it for a second button…

    Thanks again

  6. Mitch says:

    Konrad, Anything special when adding multiple Push buttons to the same panel (separate panels seems to work ok)? I defined the PB data, and image. “AddItem” will not produce another button on the panel. It will build without errors, just all buttons after that will not load. Should I be able to copy (using your code above as an example):
    // create push button for CurveTotalLength
    PushButtonData b1Data = new PushButtonData(
    “Total” + System.Environment.NewLine + ” Length “,

    PushButton pb1 = ribbonPanel.AddItem(b1Data) as PushButton;
    pb1.ToolTip = “Select Multiple Lines to Obtain Total Length”;
    BitmapImage pb1Image = new BitmapImage(new Uri(“pack://application:,,,/GrimshawRibbon;component/Resources/totalLength.png”));
    pb1.LargeImage = pb1Image;

    And redefine a new button, then add it to the same panel?

    I am looking at some examples here:

    It doesn’t look like these examples are doing anything different. Defining the push button data, then adding it to the panel. Next button, defining the push button data, then adding it to the panel.

    Looks like I’m missing something somewhere. If you have any thoughts on this, much appreciated.


Leave a Comment