Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

PostCommand: Some Commands Break When Used From Dock Pane

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
Anonymous
892 Views, 6 Replies

PostCommand: Some Commands Break When Used From Dock Pane

Hello all,

 

I've actually had this problem since 2018, I had hoped a fix would have come along but no dice...

 

We implemented a dock pane back then, and all is well with it to this day except for certain Revit commands. The vast majority of them work just fine, but for any command that requires a subsequent action in the editor Revit will not let you complete that action. Best example perpetrators are Move and Rotate, but there are others.

 

The commands execute, and you can clearly see it is active, but you cannot click or manipulate anything within the editor in order to complete the command. All you can do is cancel.

 

We have KeepAlive set on the editor, no change there. I have tried several things to fix this, up to and including using an IdleEvent and SendKeys... No matter the entry point, the result is the same.

 

I have attached a simplistic reproducible case, including bare minimum source code and pre-compiled dlls for versions 2018-2021. You just copy the addin to the appropriate location for your setup, load Revit, open any drawing, select an element and run the command from the dock pane. Pre-selection does not make a difference, though it does make the issue more obvious in my opinion...

 

There is a toggle to show/hide the dock pane if it disappears, but it should pop right up after you add it.

 

Any help is much appreciated. It may seem trivial, but our users really enjoy not having to click on tabs over and over to rerun a command. 

 

Note - We have conditional framework targeting in csproj. In case you need to know, steps to compile are:

  - Select the configuration from the dropdown in VS.

  - Unload the project

  - Reload the project

  - Rebuild

If you skip this step Revit will freak out (esp 2021). 


Folder structure for addin:
- .addin file goes at top level in desired plugin folder
- Dlls go into folder named 'Test' at same location.

 

Products Affected:

2018, 2019, 2020, 2021 (regardless of patch level)


OS info:

Windows 10 Pro 64-Bit (current, issue exists regardless of patch level)

Windows 10 Enterprise 64-Bit (previous, same issue, regardless of patch level)

Windows 8.1 (previous & some client's users, same issue)

System Info (shouldn't make a difference, as it affects everyone using our tools, but just in case):

Mine:
Dell Latitude E7250 (current)
Dell Latitude E7240 (previous)
Both Intel Core i7 VPro - 5600U @ 2.60GHz (dual core)
Samsung 860Evo mSATA 500GB (SSD)

Users:
Unknown, varied across the US.

6 REPLIES 6
Message 2 of 7
jeremytammik
in reply to: Anonymous

The dockable panel operates in a modeless context.

 

Therefore, apparently, under certain circumstances, the current document of the current view are not completely well-defined.

 

You can use the Idling or and external event to get out of the modeless context into a valid Revit API context. That night help.

 

Another thing that might help is to explicitly activate the desired document and view before launching the PostCommand call.

 

Maybe a combination of the two is required:

  

  • Dockable panel, modeless context, no access to Revit API: raise external event
  • In the event handler, first set appropriate document and view; then, call PostCommand

 

I hope this helps.

 

Please let us know how you end up solving this.

 

Thank you!

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 7
Anonymous
in reply to: Anonymous

Hello, Jeremy,

 

I am so, so sorry for the delayed response. I very much appreciate you taking the time to respond, and I appreciate the suggestions. Were you able to read or test the sample? 

 

We implemented the dock pane as an external event, already, as it is written in the sample - all i did was remove as much if not all extra fluff, as much as i could while still recreating the issue...

When the external event is called, it recieves the UIApplication as its parameter, and we are checking if a command can be posted before calling PostCommand and only posting if that returns true... The commands DO get posted, we have verified this over and over - however you cannot finish some of them. Most notable ones are Move and Rotate, things of that nature.

 

We have KeepAlive on the editor, and have tried the following as well as many, many combinations thereof just to be sure:


- Idling event, and we made sure to wait until the subsequent idle as the first fire does not work for any of them.
- Idling event several idles later to make doubly sure, same result - command initiates but you cannot complete it.
- AdWindows (I know this is not supported, but it was something we tried. No dice.)
- SendKeys, both with WinAPI and System.Windows.Input. Same result, command is posted but cannot finish.
- UIFramework direct access to buttons- same result (Also not suppored, im sure)
- AvalonDock WPF (through Reflection), same result (also not supported)
- Moving the PostCommand to be the last line in everything we tried, as suggested by documentation, also to no avail - no clue why.

However, I have not tried explicitly activating the view. I will try that now, among other things and get back to you.

If you want to look at the file that holds the external event alone, that would be DockablePaneRequestHandler.cs file in the sample project.

When i finish running through i wull update this post again, thank you for your suggestion i REALLY hope it works - we have had this issue since 2018, there is an old post i wll link to this if this works.


Maybe i missed something.

Message 4 of 7
Anonymous
in reply to: jeremytammik

@jeremytammik 

Hello again, Jeremy,

 

I am very happy to report that I did manage to get Move to work. I am certain the rest will follow suit.

 

Things of note:

- As of yet, pre-selection does NOT work - unless you call UiDocument.Show() before posting the command. I am still researching this, workaround for now is to get the zoom corners from the UIView beforehand so you can put them back. 

- You can call a FilteredElementCollector().FirstElement to bypass the pick operation, but you still have to call ShowElements() and ZoomAndCenterRectangle to avoid having the user notice a difference.

- Pick operations seem to do the trick, however it is not consistent. I will find out why. With one caveat (next)

- You absolutely HAVE to move PostCommand to the VERY end, and i do mean very as in absolute last line of the ExternalEventHandler (or otherwise, unless Modal), in order for the event to allow. However it important to note that without "activating" the view first, as was suggested, this will do nothing, and the only option for the user is to Cancel.

 

I am uncertain precisely what the bare minimum is, i will find out and post again.

 

Final question, and thank goodness for this it has been a thorn in my side for 3 years, btw - is there a "proper" way to activate a view besides a pick operation or calling ShowElements()?

 

Because knowing what i know now, i think attempting a single fire idle event will be the best route, because (afaik) you cannot stack PostCommands. So i could call the ActivateView revit command first and then on the next true idle fire the desired command. 

 

Thank you very much, i wish i had had this insight back in 2018. I scoured the interwebs and even got in a very short spat with you, btw, over this issue. I very much appreciate your help with this, i am very, very happy we can execute these properly now.

Message 5 of 7
jeremy_tammik
in reply to: Anonymous

I'm very happy to hear of your progress; congratulations!

  

Sorry that we have not gotten to this point earlier; I have pointed it out frequently in other places in the past.

 

PostCommand queues up a built-in Revit command X for execution after your current external command terminates.

 

If you want something else to happen after X completes, it is your job to ensure that happens.

 

One way (and maybe the only) is to temporarily subscribe to the Idling event.

 

That is probably all there is to say, isn't it?

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 6 of 7
Anonymous
in reply to: Anonymous

@jeremytammik @jeremy_tammik 

Not sure which is the right one, but yes - it seems that is how it operates.

 

However, while i am used to single fire idle events - for some reason this one did not take... I will continue to look, because i would much prefer to stack PostableCommand.ActivateView & the desired command because it is the most straightforward.


Here is the bare minimum it took to get it to go for us (edited):

var doc = uiDoc.Document;
var view = uiDoc.ActiveGraphicalView ?? doc.ActiveView;

var uiView = uiDoc
    .GetOpenUIViews()
    .FirstOrDefault(uv => uv.ViewId.Equals(view.Id));

//So as not to bother the user by changing the zoom
var zc = uiView.GetZoomCorners().ToList();
         
uiDoc.ShowElements(elems);

uiView.ZoomAndCenterRectangle(zc.ElementAt(0), zc.ElementAt(1));

// cmdId = RevitCommandId.LookupPostableCommandId(PostableCommand);
app.PostCommand(cmdId); //VERY last line before return to Revit

 

 

 

Thank you again for your help, this has been a deep thorn in my side for a while now.


I really appreciate it, you have no idea....

- Matt 

Message 7 of 7
Anonymous
in reply to: Anonymous

I just realized i put a custom GetUiView() command, i will adjust it.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Forma Design Contest


Rail Community