Dear Roman,
Surprise, surprise.
The development team spent a lot more time analysing and discussing REVIT-206162 [IExternalEventHandler.Execute not triggered when roof selected] and made an important observation:
I just realized what the user did is not as expected, so here is another update. Hope what I got so far provides some useful information.
After looking into the client code in revit_addin.zip, I found out they wrap the IExternalEventHandler into a custom class "ExternalEventHandler", and derive another class "ActionHandler" from it. By reading the information in the metadata of "Nice3point.Revit.Toolkit.External.ExternalEventHandler", the Revit API class "Autodesk.Revit.UI.ExternalEvent" is stored as a private member of ExternalEventHandler.
Then, in Command.cs, they creat a new ActionHandler object and raise an Action<UIApplication> inside an ExternalCommand.
That is probably where the problem comes from. When that external event is not executed immediately, it is disposed along with the disposal of the ActionHandler object. By the time Revit decides to execute the external event, the reference to that event is no longer valid. That is why the "wpEvent" is null.
As a conclusion, creating an external event and raising that event directly inside an external command is not an ideal way. I am not familiar with the initial design of the IExternalEventHandler and what is the ideal way, but based on my experience, it is better to hold the ExternalEvent object somewhere outside Revit. So I've created a sample project as a workaround. See WorkaroundDemo.mp4.
Basically I just created a winform (non-modal) that holds the external event object, so that the form won't get disposed after the command is executed. Then everything works correctly.
Here is the refined code (the ExternalEventHandler class did not change):
[Transaction(TransactionMode.Manual)]
public class ExternalEventTestCommand : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
ExecuteEventHandler handler = new ExecuteEventHandler("test");
handler.ExecuteAction = new Action<UIApplication>(app =>
{
TaskDialog.Show("test", "external event executed");
Debug.WriteLine("external event executed");
});
ExternalEvent externalEvent = ExternalEvent.Create(handler);
ExternalEventForm form = new ExternalEventForm(externalEvent);
form.Show();
return Result.Succeeded;
}
}
Best regards,
Jeremy