Revit is a powerful tool for building design and modeling, and undoubtedly, high efficiency in working with this software is a key aspect for successful projects. One of the tools that contributes to this efficiency is the OptionsBar, but not many people are aware of its capabilities and how to configure it.
OptionsBar is a convenient toolbar within Revit with tremendous potential. It offers capabilities that span from adding your own tools on the toolbar to displaying information about the operation of your own add-ins. However, the Revit API documentation doesn't offer sufficient information on fully harnessing the potential of OptionsBar.
Before we begin customizing the OptionsBar, we'll need to add the necessary dependencies and create a controller to manage this panel.
Technologies Used:
- Language: C#
- UI framework: WPF
Let's delve into the process of configuring OptionsBar and how to do it most efficiently.
Understanding that the user interface in Revit is implemented using WPF (Windows Presentation Foundation) technology helps us access all the interface elements.
For this, we'll need the AdWindows.dll
library, which comes with Revit.
To compile the project on any device, let's add a NuGet package to the .csproj
project file as follows:
<ItemGroup>
<PackageReference Include="Nice3point.Revit.Api.AdWindows" Version="$(RevitVersion).*"/>
</ItemGroup>
To control OptionsBar, we'll need a controller that handles its display and hiding.
To access the Revit ribbon and OptionsBar, we'll use the static property ComponentManager.Ribbon
from the AdWindows.dll
library that we included in the previous step.
The process of configuring OptionsBar can be divided into the following stages:
- Finding the built-in panel.
- Creating a custom panel.
- Hiding/showing the built-in and custom panels.
It's important to note that we don't remove or replace the built-in OptionsBar panel to avoid disrupting Revit's functionality. Instead, we simply hide it and display our custom panel when necessary.
Let's take a look at a code example that allows displaying and hiding the custom panel:
public static class RibbonController
{
private static readonly Grid RootGrid;
private static ContentPresenter _panelPresenter;
private static readonly FrameworkElement InternalToolPanel;
static RibbonController()
{
RootGrid = VisualUtils.FindVisualParent<Grid>(ComponentManager.Ribbon, "rootGrid");
if (RootGrid is null) throw new InvalidOperationException("Cannot find root grid in Revit UI");
InternalToolPanel = VisualUtils.FindVisualChild<DialogBarControl>(RootGrid, string.Empty);
if (InternalToolPanel is null) throw new InvalidOperationException("Cannot find internal tool panel in Revit UI");
}
public static void ShowOptionsBar(FrameworkElement content)
{
if (_panelPresenter is not null)
{
_panelPresenter.Content = content;
_panelPresenter.Visibility = Visibility.Visible;
InternalToolPanel.Height = 0;
return;
}
_panelPresenter = CreateOptionsBar();
_panelPresenter.Content = content;
InternalToolPanel.Height = 0;
}
public static void HideOptionsBar()
{
if (_panelPresenter is null) return;
_panelPresenter.Content = null;
_panelPresenter.Visibility = Visibility.Collapsed;
InternalToolPanel.Height = 26;
}
private static ContentPresenter CreateOptionsBar()
{
const int panelRow = 2;
RootGrid.RowDefinitions.Insert(2, new RowDefinition
{
Height = new GridLength(1, GridUnitType.Auto)
});
foreach (UIElement child in RootGrid.Children)
{
var row = Grid.GetRow(child);
if (row > 1) Grid.SetRow(child, row + 1);
}
var panelPresenter = new ContentPresenter();
Grid.SetRow(panelPresenter, panelRow);
RootGrid.Children.Add(panelPresenter);
return panelPresenter;
}
}
In the example, only public properties of the Revit API and system methods of WPF are used.
Interaction with the ribbon is implemented with the ShowOptionsBar()
and HideOptionsBar()
methods.
The ShowOptionsBar()
method takes any FrameworkElement, which will be displayed to the user.
To create a user interface for OptionsBar, we'll use the MVVM (Model-View-ViewModel) pattern and the WPF (Windows Presentation Foundation) framework.
For example, let's consider a simple panel layout with a text field and a dropdown list:
<StackPanel
x:Class="OptionsBar.Views.OptionsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModels="clr-namespace:OptionsBar.ViewModels"
d:DataContext="{d:DesignInstance Type=viewModels:OptionsViewModel}"
mc:Ignorable="d"
Background="#FFE5F0D7"
Orientation="Horizontal"
Height="26"
d:DesignWidth="430">
<TextBlock
Margin="10 0 0 0"
Text="Wall options"
VerticalAlignment="Center" />
<Border
Width="3"
BorderThickness="1 0"
BorderBrush="Azure"
Background="Gray"
Margin="10 0" />
<TextBlock
Text="Offset: "
VerticalAlignment="Center" />
<TextBox
Width="100"
Margin="10 1 0 1"
VerticalContentAlignment="Center"
Text="{Binding Offset, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock
Text="Constraint: "
Margin="10 0 0 0"
VerticalAlignment="Center" />
<ComboBox
Width="100"
Margin="10 1 0 1"
VerticalContentAlignment="Center"
SelectedIndex="0"
ItemsSource="{Binding Constraints}" />
</StackPanel>
Sample code for the ViewModel:
public partial class OptionsViewModel : ObservableObject
{
[ObservableProperty] private double _offset;
[ObservableProperty] private string[] _constraints;
}
The layout is no different from regular WPF applications, but the root element will be a container like StackPanel, Grid, and so on, since OptionBar is embedded in the Revit UI.
OptionsBar provides endless possibilities for streamlining the workflow in Revit. Let's explore some of the most popular use cases:
OptionsBar can be used to add custom tools that can be conveniently placed on the toolbar. This is especially useful when creating a separate window is unnecessary.
This scenario covers situations where a user is working with a model in Revit and needs to select a specific element for further editing. For more convenient and intuitive parameter customization, you can use OptionsBar instead of creating additional windows.
Example: Suppose you have a plugin that allows users to adjust the top offset of a wall. Let's see how to arrange all the tools on the OptionsBar panel.
-
Step 1: Adding OptionsBar to the Revit Ribbon
The first step in this scenario is to set up OptionsBar for display on the Revit ribbon. You can create your own view for OptionsBar with parameters that the user can customize.
Example code using the MVVM pattern:
private OptionsViewModel SetupOptionsBar() { var options = new OptionsViewModel { Offset = 0, Constraints = Document.EnumerateInstances<Level>(BuiltInCategory.OST_Levels).Select(level => level.Name).ToArray() }; var view = new OptionsView(options); RibbonController.ShowOptionsBar(view); return options; }
-
Step 2: Selecting an Element
After configuring OptionsBar, the user selects an element in the model with which they want to work. This could be, for example, selecting a wall to adjust the offset.
Example code for element selection:
private Wall PickWall() { var selectionConfiguration = new SelectionConfiguration().Allow.Element(selection => selection is Wall); var reference = UiDocument.Selection.PickObject(ObjectType.Element, selectionConfiguration.Filter, "Select wall"); return reference.ElementId.ToElement<Wall>(Document); }
-
Step 3: Adjusting Element Parameters
Now that the user has selected an element and OptionsBar is configured, you can start adjusting the element's parameters. We'll take the offset value from the ViewModel entered by the user and set it to the wall parameter.
Example code for adjusting element parameters:
private void ModifyWall(Wall wall, OptionsViewModel options) { using var transaction = new Transaction(Document); transaction.Start("Set offset"); wall.GetParameter(BuiltInParameter.WALL_TOP_OFFSET)!.Set(options.Offset); transaction.Commit(); }
-
Step 4: Restoring the Revit Ribbon
After completing the element parameter configuration, it's important to hide OptionsBar and restore the normal state of the Revit ribbon. To do this, add a
finally
block after calling all the methods.public override void Execute() { try { var options = SetupOptionsBar(); var wall = PickWall(); ModifyWall(wall, options); } catch (OperationCanceledException) { // ignored } finally { RibbonController.HideOptionsBar(); } }
This scenario allows users to quickly and conveniently customize the parameters of model elements without the need to open additional windows or perform extra actions. OptionsBar makes the process of editing elements more intuitive and efficient.
Want something unusual? A marquee can add excitement to your mundane modeling routine.
OptionsBar is a powerful tool in Revit that allows you to optimize your workflow and make it more efficient. Don't limit yourself to the described use cases — experiment, create your unique solutions, and make working in Revit even more productive.
Project source code: GitHub
Installers with examples for Revit are also available: Releases