ViewActivated Event fires multiple times when toggling between open views

ViewActivated Event fires multiple times when toggling between open views

sroswurm4GJQU
Advocate Advocate
1,897 Views
10 Replies
Message 1 of 11

ViewActivated Event fires multiple times when toggling between open views

sroswurm4GJQU
Advocate
Advocate

In my program, I have several methods that need to execute each time the user activates a different view.  These methods are triggered using the ViewActivated event.  I've been seeing some unexpected behavior which led me to break it down and do some testing with some very simplified conditions.

 

Based on my testing, I've concluded that under certain conditions the ViewActivated event appears to fire (3) consecutive times when the user has only toggled from one open view to another open view.  I verified this using a simple MessageBox.Show() which outputs the name of the newly activated view and the previously active view.  As you will see in my attached reproducible test case, I have already verified that I subscribe to the event only once.  If there was a redundant subscription to the event, I would expect the problem to manifest during all view activations, but I have only observed the behavior when toggling between already open views.  Opening a new view does not result in multiple fires of the event.  This behavior is evident in Revit 2019, Revit 2020, and in Revit 2021.

 

Here is an example of how the problem would manifest.  Say that you have two open plan views ("Level 1" and "Level 2"), where "Level 1" is currently active.  If you then activate the "Level 2" plan by clicking it's tab, then you will see three consecutive messages:

 

1.)  First, the requested view is activated:

 

sroswurm4GJQU_0-1623177678759.png

 

2.)  Then the original view is re-activated:

 

sroswurm4GJQU_1-1623177719233.png

 

3.)  Finally, the requested view is activated again:

 

sroswurm4GJQU_2-1623177750752.png

 

To demonstrate this behavior, I've created a basic test case where all of the required code is included in a macro inside the attached Revit 2020 file.  In order to observe the issue I've described here, simply open the Revit file, enable macros, and then run the RegisterEventHandler() method.  Opening several views and then toggling between them several times will eventually result in the multiple firing I'm describing.  See the link below for a short screen capture video clip of the multiple firing in action.  You will note that the behavior does not occur immediately.  It typically occurs after cycling through several open views:

 

https://www.screencast.com/t/9K7GjtMA886

 

I'm interested to hear if there is a problem with my implementation, or if there is a way to prevent this redundant firing of the event.  The repetitive firing becomes particularly problematic for any time-consuming logic inside the event, because the user begins to experience multiple unnecessary delays. 

 

@jeremytammik 

1,898 Views
10 Replies
Replies (10)
Message 2 of 11

jeremy_tammik
Alumni
Alumni

Dear Seth,

 

Thank you for your report, clear description and sample material.

 

Sorry to hear about this.

 

I logged the issue REVIT-178654 [ViewActivated fires multiple times toggling open views] with our development team for this on your behalf as it requires further exploration and possibly a modification to our software. Please make a note of this number for future reference.

 

You are welcome to request an update on the status of this issue or to provide additional information on it at any time quoting this change request number.

 

This issue is important to me. What can I do to help?

 

This issue needs to be assessed by our engineering team and prioritised against all other outstanding change requests. Any information that you can provide to influence this assessment will help. Please provide the following where possible:

 

  • Impact on your application and/or your development.
  • The number of users affected.
  • The potential revenue impact to you.
  • The potential revenue impact to Autodesk.
  • Realistic timescale over which a fix would help you.
  • In the case of a request for a new feature or a feature enhancement, please also provide detailed Use cases for the workflows that this change would address.

 

This information is extremely important. Our engineering team have limited resources, and so must focus their efforts on the highest impact items. We do understand that this will cause you delays and affect your development planning, and we appreciate your cooperation and patience.

 

Best regards,

 

Jeremy

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 11

sroswurm4GJQU
Advocate
Advocate

Jeremy,

 

Thanks for taking the time to evaluate this issue and provide an update.  I'll be interested to hear what the dev team has to say.  

 

As far as the impact of the issue, I would be inclined to say it's problematic for nearly any developer who might care to execute code inside the ViewActivated event.  In addition to the risk of performing redundant or repetitive actions in the document, there is also the time lost while the actions occur repeatedly.  If for some reason any method contained inside the event had a UI component, such as a form pop-up or similar, the end user would then be presented with redundant pop-ups for no reason. 

 

Another significant risk (which manifested in our specific case) is accidental undocking of views in the Revit interface.  We received multiple reports of unwanted undocking of views from various users, which is what prompted this discovery.  From my testing, it appears that Revit forces user focus to remain on the view whose ViewActivated event is currently executing.  So if you try to rapidly change views again while an event is already executing, then Revit automatically turns your single click of the view tab into a "grab and hold" in order to keep focus on the view.  This means that when you move your cursor off the view tab bar, Revit automatically breaks off the view into its own window.  Now this is most likely an issue with long-running events even without the multiple firing bug.  But the repetitive raising of the event exponentially increases your odds of accidentally undocking a view because you moved your cursor during event execution.  Prior to the release of our update which resolved this issue, one user confessed that the undocking became so invasive that he disabled our application.  So there is a definite business risk for any developer or vendor who relies on the ViewActivated event.

 

In my specific case, the only clear path to circumvent the issue was to completely alter my program so that I no longer explicitly rely on the ViewActivated event to trigger my logic when toggling between open views.  Instead, the firing of this event is only critical when a new view is opened, which in my testing did not appear to correlate to multiple event firings.  In addition, the actions I needed to execute have been moved to a background thread which now uses an External Event to interact with the Document.  The background thread also has to make use of the ExternalEvent.IsPending property in case many view changes occur in rapid succession.  Although moving to another thread still uses up local machine resources and risks redundant action in the Document, it prevents the user from experiencing hangs or wait times caused by the multiple event fires.

 

So in my specific case, we are still able to provide an acceptable user experience because the cost was born by our dev team rather than the end user.  But one can envision scenarios where a valid workaround may not afford the exact experience you want to provide for your users.  The issue also dramatically increases the complexity needed to safely implement the ViewActivated event and requires great caution to prevent frustrating unwanted behavior of views in the user's Revit GUI.

 

Thanks,

Seth

Message 4 of 11

jeremy_tammik
Alumni
Alumni

Dear Seth,

 

Thank you for your appreciation, the detailed explanation and business case.

 

The development team confirmed this behaviour and opened a new development ticket REVIT-180990 [ViewActivated fires multiple times toggling open views] to perform the actual development work for it. Please make a note of this number for future reference.

 

They also added: First off, kudos for an excellent bug report. So thank you for that as well.

 

Best regards,

 

Jeremy

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 5 of 11

Sean_Page
Collaborator
Collaborator

Are you running the macro multiple times and/or on multiple documents? When I first open up the file and push "Run" on the RegisterEvent it appears to work as expected, but then if I press it multiple more time the I get additional pop ups for each time its pressed. Likewise with the UnregisterEvent. I have to "Run" it the same number of times to get it to stop giving me the popup.

 

Typically you see these events registered once in the Startup and then unregistered in the Shutdown I think to avoid this type of overlap.

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes
Message 6 of 11

sroswurm4GJQU
Advocate
Advocate

For clarity, the test case I provided is a document-level macro.  So there are no other Documents in play.

 

You're correct in saying that for simplicity the original reproducible case did no include protections against redundant registry of the ViewActivated event handler.  However, I do not believe that's the root cause of the undesired behavior.  You will note in the original macro that the MessageBox.Show() action deliberately extracts information from the ViewActivatedEventArgs to make it obvious whether the same EventArgs were captured twice (as in the case of a redundant registry).  You'll note in the clips linked below that instead of showing redundant EventArgs information, Revit is generating multiple events with different EventArgs.

 

You can reproduce the problematic behavior even with the following protections in place:

 

  • Changing the macro to Register the event in Module_Startup() and Unregister in Module_Shutdown()
  • Adding a static bool variable to the macro and using it to prohibit redundant registrations. 

The repetitive firing of the event still manifests even without the risk of repeat registry.  Please see the attached .rvt file with the macro updated to include the above precautions.  You'll note in the screencast clips linked below that the multiple firing of the event does not manifest on the very first active view change.  It typically only manifests on subsequent changes.  You'll also note in the clip that the behavior is not perfectly stable.  In the first clip, although the multiple firing occurs many times initially, it ceases after the manual triggering of the Register() method.  Conversely, you'll observe that in the second clip the multiple firing initially does not occur, but then begins after manual triggering of the Register() method. 

 

In both cases, however, the Register() method actually causes no change to the registry status because the conditional logic based on the bool prevents it.  In view of that fact, there is likely no correlation whatsoever between the Register() method being raised and the redundant firing either happening or not happening.  More than likely, it has to do with an instability on the Revit side, which will be resolved by the dev ticket @jeremy_tammik mentioned.

 

https://www.screencast.com/t/McmV0OYZo 

 

https://www.screencast.com/t/DEFTdNWQ9twZ 

0 Likes
Message 7 of 11

Sean_Page
Collaborator
Collaborator

I will be interested to hear back from the Dev team, but I have numerous things tied to the ViewActivated handler (full add-in not Macro) and I do not have any issues with multiple firing.

 

For reference:

Screenshot_20210909-184743.png

https://knowledge.autodesk.com/support/revit/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/Revit-C...

 

 

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes
Message 8 of 11

sroswurm4GJQU
Advocate
Advocate

Yeah, I would think that is definitely something to watch out for if you work in macros.  Normally, I handle all Register and Unregister actions inside the OnStartup() and OnShutdown() methods in my External Applications.  I never use macros for anything except reproducible cases for bug reports, based on @jeremy_tammik 's recommendation that the self-contained nature makes it easier for the dev team to analyze.  Since I don't use them daily, I might have taken a not-so-recommended approach for registering.  I was able to isolate the issue originally in my full application, but went all the way back to a simple macro to document it.

 

Since you have add-ins that rely on ViewActivated, I'd be interested to hear more about your use cases.  Is it conceivable in any way that you could have multiple firings of the event without knowing it?  We had it happening in our app for a while without realizing it. 

 

You may be interested in testing out the External Application code here and seeing what it does.  When I open any Revit project while running this very basic external app, it reproduces the exact same multiple firing issue we've been discussing, just like clock-work.  As I mentioned earlier, the problem is not 100% stable, so you may have to spend some time moving from view to view before you see it happen.  It manifests as (3) consecutive pop-ups instead of the single that you would expect.  Here's the code:

 

using System;
using System.Windows.Forms;
using Autodesk.Revit.UI.Events;
using Autodesk.Revit.UI;

namespace ViewActivated_Test_Application
{
    public class App : IExternalApplication
    {
        public Result OnStartup(UIControlledApplication application)
        {
            //Register an event handler for activating a view
            application.ViewActivated += new EventHandler
                 <Autodesk.Revit.UI.Events.ViewActivatedEventArgs> 
                 (viewActivatedMethod);

            //Notify the user that the external app has loaded
            MessageBox.Show("ViewActivated_Test_Application has loaded." + 
                            "\n" + 
                            "ViewActivated event has been registered.");

            return Result.Succeeded;
        }

        public Result OnShutdown(UIControlledApplication application)
        {
            //Unregister the event handler
            application.ViewActivated -= viewActivatedMethod;

            return Result.Succeeded;
        }

        public static void viewActivatedMethod(object sender, 
                                               ViewActivatedEventArgs args)
        {
            //Report the results from the ViewActivatedEventArgs
            MessageBox.Show("View activation finished: " + "\n" + "\n" +
                            "New View Name: " + args.CurrentActiveView.Name + 
                            "\n" + "\n" +
                            "Previous View Name: " + 
                            args.PreviousActiveView.Name);
        }
    }
}

 

And here is the manifest file to load it:

 

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<RevitAddIns>

  <AddIn Type="Application">
    <Name>Test External Application</Name>
    <Assembly>//Insert assembly path here</Assembly>
    <AddInId>//Insert GUID here </AddInId>
    <FullClassName>ViewActivated_Test_Application.App</FullClassName>
    <VendorId>Vendor</VendorId>
    <VendorDescription>Vendor</VendorDescription>
  </AddIn>

</RevitAddIns>

 

I'm interested to hear your thoughts if you get a chance to try this out.

0 Likes
Message 9 of 11

Sean_Page
Collaborator
Collaborator

Ok, so I built your test App, and I have figured out what it is doing. Since you are using the args for the MessageBox, and presumably in your production app, the PreviousView and CurrentView properties return a View.

 

spage_0-1631251591671.png

 

So, therefore it is "Activating" that view again to pull information (Name) from it. I discovered since the values kept changing as you described, and I seen the actual view change in the background between Message boxes. Once I removed the args for previous and current it only fired once no matter how many times nor how fast I tried to do it.

 

Not sure what you are doing, but perhaps the ViewActivatingEvent could work better, but haven't tested at all.

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
Message 10 of 11

sroswurm4GJQU
Advocate
Advocate

I'm not aware that obtaining a reference to a view forcibly activates it in the UIDocument.  While I do see that the Revit UI is shifting focus between the current and present views, this doesn't seem to be caused by simply getting views from the args.  If that were the case, I would think that referencing both the current and previous views would put you into an infinite loop.  If getting a reference to the previous view forcibly activated it, then the event would fire continuously with no way to escape the back-and-forth.

 

I ran a simple test on your theory by commenting out my use of the event args and using only plain text in the MessageBox:

 

        public static void viewActivatedMethod(object sender, 
                                               ViewActivatedEventArgs args)
        {
            ////Report the results from the ViewActivatedEventArgs
            //MessageBox.Show("View activation finished: " + "\n" + "\n" +
            //"New View Name: " + args.CurrentActiveView.Name + "\n" + "\n" +
            //"Previous View Name: " + args.PreviousActiveView.Name);

            //Notify that the event has fired
            MessageBox.Show("View activation finished!");
        }

 

 After navigating around from view to view for a while, the same issue eventually resurfaces:

 

https://www.screencast.com/t/GEbVohxEh 

0 Likes
Message 11 of 11

bnewcombe
Contributor
Contributor

If you tile the views this activity stops, the multiple viewactived event firing must be related to the tabbed views. I have checked this activity ceases in the macro you created and in an application i am developing which suffered the same issue. Are there any updates to this issue?

 

cheers