How to definitely get the current UIView even if the Focus is not on a UIView?

How to definitely get the current UIView even if the Focus is not on a UIView?

jlpgy
Advocate Advocate
3,545 Views
5 Replies
Message 1 of 6

How to definitely get the current UIView even if the Focus is not on a UIView?

jlpgy
Advocate
Advocate

I'm facing a problem with the usage of UIView class.

There are several useful instance method in this class, and only 2 instance properties: IsValidObject & ViewID.

An instance must be got ahead of anything I want to do, so I packed the following lines into an extension method:

        /// <summary>
        /// 获取 UIDocument 的 UIView,用于控制视图显示。
        /// </summary>
        public static UIView ActiveUIView(this UIDocument uiDoc)
        {
            // var uiViews = uiDoc?.GetOpenUIViews();
            return uiDoc?.GetOpenUIViews()?.FirstOrDefault(item => item.ViewId == uiDoc.ActiveView.Id);
        }

It looks good ... for now. I have some codes in an external command. In this command, I use an UIDocument instance which is provided by commandData, to get the CURRENT ACTIVE UIView.

But, If I click the project browser dock pane ahead of triggering my external command, like this:图像 2.png

 You can see now the focus is at Project Browser pane, and my cursor is pointing at my own command PushButton, without clicking it(focus still at Project Browser). I Click my own command which calls the above mentioned method. It will return null. 😞

I'll show you the debugging status:图像 2.png

 You can see the ActiveView property is an object of type View, but usually an meaningful view should be of Type View3D, ViewPlan, ViewSection, and so on.

It's name is "Project View", it has an ID that reads 230, but most element ID a programmer should be dealing with is an integer with six numbers.

And let's see more:图像 2.png

 Title is "Project Browser", no ViewName (meaning less).

I do understand that the browser is also a View element in Revit. But under this circumstance (user click Project Browser ahead of triggering an external command), how can I still keep tracking THE view that the user want to work in ?

Think about this circumstance:

  • There are 2 doc views opened, both of which are plan views
  • Then he clicks Project Browser, which means focus now is at Project Browser pane
  • Then he clicks an add-in command, which works in a plan view
  • Now, how can I track WHICH plan view he wants to work in???
  • Further thinking, if two plan views opened, for 2 different .rvt documents???

 

I was thinking that when DocumentOpened, a default view will be ALWAYS opened, But I cannot get UI Views, because DocumentOpened is an App level event.

I was also thinking about using Idling event, but it is still not strict enough. Because after opening a document, and before the user triggers any add-in command, I am not able to get a CommandData instance, which helps me tracking opened UIViews, or any other useful things.

 

Any solution or workaround for this? Within API, or with the help of some windows programming workaround?

thanks!

 

===============

 

Another small user story here:

When I was testing with Revit 2018.3, I found an interesting behavior.

If I click somewhere in the Property dock pane, the Property pane gets focused. Then if I move mouse cursor outside the pane, the FORMER view will gets focused immediately.

For example, I click Project Browser first; Second, I click Property pane; Then I move mouse cursor out from Properties pane, the Project Browser pane gets focused. This happens even if I move mouse cursor directly into an opened UI View. Where ever I move mouse, the former view gets focused. 

If I click in a ViewPlan(commonly working view), the click Properties pane, then move out cursor, ViewPlan gets focused, because I can see the Properties pane flashed to update all properties, also, this movement triggers ExternalCommandAvailibility.Excute() method.图像 2.png

 

 

Like the above illustration, Focus stays in Properties pane.  🙂

 

A short user story, not quite big deal but interesting.

 

 

 

 

 

 

单身狗;代码狗;健身狗;jolinpiggy@hotmail.com
Accepted solutions (1)
3,546 Views
5 Replies
Replies (5)
Message 2 of 6

stever66
Advisor
Advisor

@jlpgy wrote:

I'm facing a problem with the usage of UIView class.

There are several useful instance method in this class, and only 2 instance properties: IsValidObject & ViewID.

An instance must be got ahead of anything I want to do, so I packed the following lines into an extension method:

        /// <summary>
        /// 获取 UIDocument 的 UIView,用于控制视图显示。
        /// </summary>
        public static UIView ActiveUIView(this UIDocument uiDoc)
        {
            // var uiViews = uiDoc?.GetOpenUIViews();
            return uiDoc?.GetOpenUIViews()?.FirstOrDefault(item => item.ViewId == uiDoc.ActiveView.Id);
        }

It looks good ... for now. I have some codes in an external command. In this command, I use an UIDocument instance which is provided by commandData, to get the CURRENT ACTIVE UIView.

But, If I click the project browser dock pane ahead of triggering my external command, like this:图像 2.png

 You can see now the focus is at Project Browser pane, and my cursor is pointing at my own command PushButton, without clicking it(focus still at Project Browser). I Click my own command which calls the above mentioned method. It will return null. 😞

I'll show you the debugging status:图像 2.png

 You can see the ActiveView property is an object of type View, but usually an meaningful view should be of Type View3D, ViewPlan, ViewSection, and so on.

It's name is "Project View", it has an ID that reads 230, but most element ID a programmer should be dealing with is an integer with six numbers.

And let's see more:图像 2.png

 Title is "Project Browser", no ViewName (meaning less).

I do understand that the browser is also a View element in Revit. But under this circumstance (user click Project Browser ahead of triggering an external command), how can I still keep tracking THE view that the user want to work in ?

Think about this circumstance:

  • There are 2 doc views opened, both of which are plan views
  • Then he clicks Project Browser, which means focus now is at Project Browser pane
  • Then he clicks an add-in command, which works in a plan view
  • Now, how can I track WHICH plan view he wants to work in???
  • Further thinking, if two plan views opened, for 2 different .rvt documents???

 

I was thinking that when DocumentOpened, a default view will be ALWAYS opened, But I cannot get UI Views, because DocumentOpened is an App level event.

I was also thinking about using Idling event, but it is still not strict enough. Because after opening a document, and before the user triggers any add-in command, I am not able to get a CommandData instance, which helps me tracking opened UIViews, or any other useful things.

 

Any solution or workaround for this? Within API, or with the help of some windows programming workaround?

thanks!

 

===============

 

Another small user story here:

When I was testing with Revit 2018.3, I found an interesting behavior.

If I click somewhere in the Property dock pane, the Property pane gets focused. Then if I move mouse cursor outside the pane, the FORMER view will gets focused immediately.

For example, I click Project Browser first; Second, I click Property pane; Then I move mouse cursor out from Properties pane, the Project Browser pane gets focused. This happens even if I move mouse cursor directly into an opened UI View. Where ever I move mouse, the former view gets focused. 

If I click in a ViewPlan(commonly working view), the click Properties pane, then move out cursor, ViewPlan gets focused, because I can see the Properties pane flashed to update all properties, also, this movement triggers ExternalCommandAvailibility.Excute() method.图像 2.png

 

 

Like the above illustration, Focus stays in Properties 

 

 



I think this should be all you need to get the active view:

 


Autodesk.Revit.DB.View pView = ActiveUIDocument.Document.ActiveView;

 

Notice that  it uses the "document" instead of the "uidoc" and it's a view type instead of a uiview type.  So it should not return any views related to the user interface.

 

 

 

 

0 Likes
Message 3 of 6

jlpgy
Advocate
Advocate

Thank you for you reply!

But what I want to get is UIView, because it's the only class that provides the window displaying the active VIEW.

I need this UIView to get the displaying window coordinate.

I think it's the only class to get the information of the displaying window.

单身狗;代码狗;健身狗;jolinpiggy@hotmail.com
0 Likes
Message 4 of 6

FAIR59
Advisor
Advisor

see my answer to this question https://forums.autodesk.com/t5/revit-api-forum/getting-screen-coordinate-from-revit-coordinate/m-p/7...

It's an method with an activeView, but it might with a little adaption also work for your problem.

0 Likes
Message 5 of 6

jlpgy
Advocate
Advocate

@FAIR59

Thank you for your suggestion.

I have tested, but it still could not solve this problem.

Notice that in your codes, Document.ActiveView property is still used. I used the same property in my code.

But, if you click the Project Browser pane, the ActiveView is actually a View that displaying the browser. In my computer, which runs Revit 2018.3, the ID of this View is usually an integer with 3 numbers. For example, 210, 233......

 

My thought is, if I use the ActiveView property, and do some comparison with all UIView objects from GetOpenUIViews() method, it will never work.

 

I'm thinking of recording the LAST FOCUSED UIView, but don't know how... 😞

Maybe I should use IExternalCommandAvailablity to block the command push button, if the user doesn't click an effective UIView window.

 

Thank you again

单身狗;代码狗;健身狗;jolinpiggy@hotmail.com
0 Likes
Message 6 of 6

FAIR59
Advisor
Advisor
Accepted solution

the property you are looking for is UIDocument.ActiveGraphicalView.