Commands

Commands

The Revit API provides access to existing Revit commands, either located on a tab, the application menu, or right-click menu. The main ways to work with Revit commands using the API is to either replace the existing command implementation or to post a command.

Overriding a Revit command

The AddInCommandBinding class can be used to override an existing command in Revit. It has three events related to replacing the existing command implementation.

  • BeforeExecuted- This read-only event occurs before the associated command executes. An application can react to this event but cannot make changes to documents, or affect the invocation of the command.
  • CanExecute - Occurs when the associated command initiates a check to determine whether the command can be executed on the command target.
  • Executed - This event occurs when the associated command executes and is where any overriding implementation should be performed.

To create the commandbinding, call either UIApplication.CreateAddInCommandBinding() or UIControlledApplication.CreateAddInCommandBinding(). Both methods require a RevitCommandId id to identify the command handler you want to replace. The RevitCommandId has two static methods for obtaining a command's id:

  • LookupCommandId - Retrieves the Revit command id with the given id string. To find the command id string, open a session of Revit, invoke the desired command, close Revit, then look in the journal from that session. The "Jrn.Command" entry that was recorded when it was selected will have the string needed for LookupCommandId() and will look something like "ID_EDIT_DESIGNOPTIONS".
  • LookupPostableCommandId - Retrieves the Revit command id using the PostableCommand enumeration. This only works for commands which are postable (discussed in the following section).

The following example, taken from Revit 2014 SDK's DisableCommand sample, demonstrates how to create an AddInCommandBinding and override the implementation to disable the command with a message to the user.

Code Region: Overriding a command

/// <summary>
/// Implements the Revit add-in interface IExternalApplication
/// </summary>
public class Application : IExternalApplication
{
    #region IExternalApplication Members
      
    /// <summary>
    /// Implements the OnStartup event
    /// </summary>
    /// <param name="application"></param>
    /// <returns></returns>
    public Result OnStartup(UIControlledApplication application)
    {
        // Lookup the desired command by name
        s_commandId = RevitCommandId.LookupCommandId(s_commandToDisable);

        // Confirm that the command can be overridden
        if (!s_commandId.CanHaveBinding)
        {
            ShowDialog("Error", "The target command " + s_commandToDisable +
                        " selected for disabling cannot be overridden");
   return Result.Failed;
        }

        // Create a binding to override the command.
        // Note that you could also implement .CanExecute to override the accessibiliy of the command.
        // Doing so would allow the command to be grayed out permanently or selectively, however,
        // no feedback would be available to the user about why the command is grayed out.
        try
        {
            AddInCommandBinding commandBinding = application.CreateAddInCommandBinding(s_commandId);
            commandBinding.Executed += DisableEvent;
        }
        // Most likely, this is because someone else has bound this command already.
        catch (Exception)
        {
            ShowDialog("Error", "This add-in is unable to disable the target command " + s_commandToDisable +
                        "; most likely another add-in has overridden this command.");
        }

        return Result.Succeeded;
    }

    /// <summary>
    /// Implements the OnShutdown event
    /// </summary>
    /// <param name="application"></param>
    /// <returns></returns>
    public Result OnShutdown(UIControlledApplication application)
    {
        // Remove the command binding on shutdown
        if (s_commandId.HasBinding)
            application.RemoveAddInCommandBinding(s_commandId);
        return Result.Succeeded;
    }

    #endregion

    /// <summary>
    /// A command execution method which disables any command it is applied to (with a user-visible message).
    /// </summary>
    /// <param name="sender">Event sender.</param>
    /// <param name="args">Arguments.</param>
    private void DisableEvent(object sender, ExecutedEventArgs args)
    {
        ShowDialog("Disabled", "Use of this command has been disabled.");
    }

    /// <summary>
    /// Show a task dialog with a message and title.
    /// </summary>
    /// <param name="title">The title.</param>
    /// <param name="message">The message.</param>
    private static void ShowDialog(string title, string message)
    {
        // Show the user a message.
        TaskDialog td = new TaskDialog(title)
        {
            MainInstruction = message,
            TitleAutoPrefix = false
        };
        td.Show();
    }

    /// <summary>
    /// The string name of the command to disable.  To lookup a command id string, open a session of Revit,
    /// invoke the desired command, close Revit, then look to the journal from that session.  The command
    /// id string will be toward the end of the journal, look for the "Jrn.Command" entry that was recorded
    /// when it was selected.
    /// </summary>
    static String s_commandToDisable = "ID_EDIT_DESIGNOPTIONS";

    /// <summary>
    /// The command id, stored statically to allow for removal of the command binding.
    /// </summary>
    static RevitCommandId s_commandId;

}

Posting a command

The method UIApplication.PostCommand() will post a command to the Revit message queue to be invoked when control returns from the current API application. Only certain commands can be posted this way. They include all of the commands in the Autodesk.Revit.UI.PostableCommand enumerated type as well as external commands created by any add-in.

Note: Even a postable command may not execute when using PostCommand(). One reason this may happen is if another command has already been posted. Only one command may be posted to Revit at a given time, so if a second command is posted, PostCommand() will throw an exception. Another reason a posted command may not execute is if the command to be executed is not accessible at the time. Whether it is accessible is determined only at the point where Revit returns from the API context, so a failure to execute for this reason will not be reported directly back to the application that posted the command.

UIApplication. CanPostCommand() can be used to identify if the given command can be posted, meaning whether it is a member of PostableCommand or an external command. It does not identify if the command is currently accessible.

Both PostCommand() and CanPostCommand() require a RevitCommandId which can be obtained as described in the "Overriding a Revit command" section above.