DockablePane in Zero Document State

DockablePane in Zero Document State

lwlXUTTT
Advocate Advocate
1,094 Views
8 Replies
Message 1 of 9

DockablePane in Zero Document State

lwlXUTTT
Advocate
Advocate

Dear Community,

 

I have my DockablePane registered OnApplicationInitialized

public class MainApplication : IExternalApplication
{
   public Result OnStartup(UIControlledApplication uiControlledApp)
   {
      ControlledApplication.ApplicationInitialized += OnApplicationInitialized;
   }

   private static void OnApplicationInitialized(object sender, Autodesk.Revit.DB.Events.ApplicationInitializedEventArgs e)
   {
      MyDockablePane.Register(UiControlledApp);
   }
}

 

I can see that DockablePane is already registred after Application is initialized, but the Show() method becomes effective(visible) only when any Document is opened. Is there a way to have my custom DockablePane visible/accessible without having any document open?

- simirarly to Ribbon Buttons, which can be accesed in Zero Document State with proper implementation of IExternalCommandAvailability..

 

Any feedback would be much appreciated,

Best, Lukasz

0 Likes
Accepted solutions (1)
1,095 Views
8 Replies
Replies (8)
Message 2 of 9

ricaun
Advisor
Advisor
I believe the DockablePane is designed to only appear when a document is opened, like the Proprietes or Project Browser.

I used a mix of View and DockablePane to make work with document and without document.
Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 3 of 9

lwlXUTTT
Advocate
Advocate

Hello @ricaun.,

 

Thank you for your answer.

I used a mix of View and DockablePane

I don't quite understand what you mean by this. May I ask you to elaborate a bit on that?

 

I made a test with WPF Window that sets RevitMainWindowHandle as its Owner. the result is similar to DockablePane, but what is obviously missing is its ability to be 'Docked' inside Revit UI Elements....

Implementation below:

public partial class MyWindow : Window
{
   public void AssignOwner(UIApplication UiApp)
   {
      IntPtr RevitMainWindowHandle = UiApp.MainWindowHandle;

      WindowInteropHelper helper = new WindowInteropHelper(this);
      helper.Owner = RevitMainWindowHandle;
   }
}

 

Looking forward for your answer,

Lukasz

0 Likes
Message 4 of 9

ricaun
Advisor
Advisor
I misspell View, should be a WPF Window 🙃

In my case, I only open the WPF if the user tries to open the dockable pane when has no document, and is possible to have WPF and dockable pane opened at the same time. This is not a problem in my plugin this behavior, I could make Windows close when a document is opened/created and force the dockable to show.
Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 5 of 9

lwlXUTTT
Advocate
Advocate

Hi @ricaun ,

 

Thank you for a brief answer. The solution of a global static switch, which changes the referenced object (WPF-Window/DockablePane)  may be a solution.

 

But I would have two more questions regarding this approach:

  • when do you actually register DockablePane. I used to do this OnApplicationInitialized, but I have found out that, when Revit Document is open directly from file (e.g. doubleclick on detached .rvt file), first the event of DocumentOpend is called and then ApplicationInitialized. This causes an error - trying to show DockablePane which is not registered yet.

 

  • Capture.JPG

     Secondly - do you have a separate WPF FrameworkElement class for DockablePane and separate for WPF Window? If not, how do you deal with TitleBar with buttons (close / minimize etc)? DockablePane has those built in...

Looking forward,

Best, Lukasz

0 Likes
Message 6 of 9

ricaun
Advisor
Advisor

I register the DockablePane inside the OnStartup, I don't use ApplicationInitialized, but is kinda odd that DocumentOpened triggers before ApplicationInitialized. I always assume the ApplicationInitialized is triggered when all the plugins was loaded and the Revit is ready to open a document... 'The event is raised after Revit was launched as fully initialized, including initialization of external applications.

 

The Revit API guide said:
ApplicationInitialized - notification after the Revit application has been initialized, after all external applications have been started and the application is ready to work with documents

Maybe the ApplicationInitialized triggers when the first Idling is trigged.

 

In my Window I'm using the same Page that is used in the IDockablePaneProvider, the same FrameworkElement.
In my xaml Window I have something like this:

<local:MyDockablePane Margin="5"></local:MyDockablePane >

The content gonna be the same, the close button usually works out of the box, and minimize/resize I usually disable it with the Icon in the toolbar.

this.ShowInTaskbar = false;
this.ResizeMode = ResizeMode.NoResize;

 

Unfortunately, I don't have an example project with Window/DockablePane to share, maybe I create one just to check this ApplicationInitialized/DocumentOpened behavior.

 

PS: Are you creating a console inside Revit? I have a plugin that does exactly that and other bonuses.

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 7 of 9

lwlXUTTT
Advocate
Advocate

Hello @ricaun,

 

I have tested you approach - sound like a reasonable solution.

So, firstly I have assigned a static trigger to my IExternalApplication, which switches between WPF-Window / DockablePane, depending on two conditions: 1. Is DockablePane already registered 2.Is at least one Document opened.

Then I play with Show() / Hide () methods. Logic-wise this works without any problems.

 

For that I am using one Page class (Singleton object), which is:

  • on one hand registered as DockablePane
  • on the other hand, serves as content for my WPF-Window

And this is where the problem appears. Problem is with UI display - no exceptions are thown during App Runtime. If I have only DockablePane registered (no instance of WPF-Window instance created) everything works. Simirarly, if I create a instance of my WPF-Window (no DockablePane registered) everything works as well. But if I show both at the same time, frame of both are visible, but no content, so no Page class instance (UI-wise).... Do you have any idea why this can be like this ?

 

Below my implementation

//ContentPage implemented as Singleton object

 

public partial class ContentPage : Page, INotifyPropertyChanged, IDockablePaneProvider
{
   //Singleton implementation
   public static ContentPage Instance
   {
      if (_instance == null)
         _instance = new ContentPage();
      return _instance;
   }
}

 

 

DockablePane as already mentioned is registered OnApplicationInitialized (so far...)

uiControlledApp.RegisterDockablePane(dpid, "MyTitle", ContentPage.Instance as IDockablePaneProvider);

 

//WPF-Window also implemented as Singleton object

 

public partial class WPF_Window : Window
{
   public static WPF_Window Instance
   {
      if (_instance == null)
      _instance = new WPF_Window();

      return _instance;
   }

   private WPF_Window()
   {
      InitializeComponent();
      //XAML bounding to ContentPage Singleton instance
      MainContent.Content = ContentPage.Instance;
   }
}

 

 

//XAML content bounding to ContentPage:

 

<Window.Content>
   <Frame x:Name="MainContent" NavigationUIVisibility="Hidden"/>
</Window.Content>

 

 

I don't think that it has anything to do with my Singleton objects.. I would rather see the problem in the BlackBox which is the Registering of DockablePane...

 

I would grately appreciate your feedback,

Best, Lukasz

 

PS. Yes, I am trying to built a sort of output window, which would damp everything that is happening in my IExternalApplication

0 Likes
Message 8 of 9

ricaun
Advisor
Advisor
Accepted solution

In my case, I'm not using Singleton on the Page. But inside the Page I'm using a Singleton for the DataContext.


Maybe that's the problem, I guess you are not allowed the same FrameworkElement instance in two places.

 

Try to not use the Singleton on the Page to test.

 

public partial class MyDockablePage : Page, IDockablePaneProvider
{
    public MyDockablePage()
    {
        this.DataContext = MyDockableViewModel.ViewModel;
        InitializeComponent();
    }
    public void SetupDockablePane(DockablePaneProviderData data)
    {
        data.FrameworkElement = this;
        data.InitialState = new DockablePaneState
        {
            DockPosition = DockPosition.Right,
        };
        data.VisibleByDefault = false;
    }
}

 Here is how MyDockablePage code sample. I'm using Singleton ViewModel so the data that gonna appear in the DockablePane gonna be the same in the Window.

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 9 of 9

lwlXUTTT
Advocate
Advocate

Hi @ricaun ,

 

Thank you for your suggestion - that did the trick, assigning DataContext to Singleton instance Of ViewModel works perfectly!

One more thing woth to point out - when checking the number of opened documents (to determine whether window should be displayed as WPF-Window or DockablePane) both event should be considered:

  • DocumentOpened
  • DocumentCreated

The latter one is raised when document is created but also when existing family instance is edited from Project Document context,

 

all the best, Lukasz

 

0 Likes