Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I raise an external event in the Revit API from a WPF app?

I have been trying to create a Revit plugin that allows the user to view issues that are stored on a remote server on the local version of the file. It should create a new 3D perspective view from the stored data on the server and open it in Revit. However, whenever I attempt to run it, I get an exception warning thusly:

Exception thrown: 'Autodesk.Revit.Exceptions.InvalidOperationException' in RevitAPIUI.dll
An unhandled exception of type 'Autodesk.Revit.Exceptions.InvalidOperationException' occurred in RevitAPIUI.dll
Attempting to create an ExternalEvent outside of a standard API execution

I think I understand vaguely what this means, but I am unsure what exactly needs to be changed to fix it. I am defining a custom ExternalEventHandler and implementing its Execute method:

class CameraEventHandler : IExternalEventHandler
    {
        Issue issue;
        int i;

        public CameraEventHandler(Issue issue, int index)
        {
            this.issue = issue;
            this.i = index;
        }

        public void Execute(UIApplication app)
        {
            Document doc = app.ActiveUIDocument.Document;
            using (Transaction t = new Transaction(doc, "CameraTransaction"))
            {
                t.Start();
                ...
                //Irrelevant code to set camera position programmatically
                ...
                t.Commit();
            }
        }

        public string GetName()
        {
            return "Camera event handler";
        }
    }

And then in one of my WPF forms, I create an ExternalEvent and calling the Raise method:

private void RevitViewButton_Click(object sender, RoutedEventArgs e)
        {
            CameraEventHandler handler = new CameraEventHandler(issue, issueIndex);
            ExternalEvent cameraEvent = ExternalEvent.Create(handler);
            cameraEvent.Raise();
        }

However, the exception is thrown when it reaches the ExternalEvent.Create method.

Edit: I feel it is worth mentioning that the WPF app I am using is launched as a Revit plugin.

like image 871
Tom Paganuzzi Avatar asked Dec 18 '25 13:12

Tom Paganuzzi


2 Answers

  • The Revit API cannot be used outside a valid Revit API context

  • The key is that all communication between the outside thread and Revit API must be done either inside a handler of an Idling event or an External Event.

  • Such a context is only available within callback methods that you provide to Revit and that Revit calls back when it is ready to accept your input.

  • A typical example of such a callback method is the Execute method of an external command.

Driving Revit from Outside through an External Event:

IExternalEventHandler handler_event
    = new ExternalEventMy();
 
  ExternalEvent exEvent
    = ExternalEvent.Create( handler_event );
  

The external event handler class implements the actions I need to execute in a valid Revit API context:

class ExternalEventMy : IExternalEventHandler
  {
    public void Execute(UIApplication uiapp)
    {
      UIDocument uidoc = uiapp.ActiveDocument;
      if( null == uidoc )
      {
        return; // no document, nothing to do
      }
      Document doc = uidoc.Document;
      using( Transaction tx = new Transaction(doc))
      {
        tx.Start("MyEvent");
        // Action within valid Revit API context thread
        tx.Commit();
      }
    }
    public string GetName()
    {
      return "my event";
    }
  }

I can raise the external event from another thread like this:

  exEvent.Raise();
  • Use of the Revit API Requires a Valid Context
  • Revit API Context Summary

That is not a bug, Gaz, it is by design.

The solution suggested by Gaz is absolutely correct!

like image 116
Jeremy Tammik Avatar answered Dec 21 '25 02:12

Jeremy Tammik


Reading this blog it would appear to be a bug in Revit.

The solution appears to be to create your custom handler during IExternalCommand.Execute or IExternalApplication.OnStartup, rather than at the time of raising the event.

like image 31
GazTheDestroyer Avatar answered Dec 21 '25 01:12

GazTheDestroyer