How to coordinate multiple docksites and multiple regions?

Docking/MDI for WPF Forum

Posted 7 years ago by Tony Pulokas
Version: 11.1.0544
Avatar
I've got a docksite assigned to a Prism region that is dynamically loaded with documents by adding viewmodels to the region. Now, this all works just fine, and the region manager ensures that only the active viewmodel's commands are responded to (this was all discussed here).

However, the application I am working on must have two docksites and I'm not sure how best to proceed. I can think of two paths forward.

1. Two docksites, each with its own region.
    The regions will need to coordinate with each other as to which should inactivate all its viewmodels and which should have one active viewmodel.
    One issue with this approach: clicking into tabbed documents across docksites/regions doesn't activate the document you click on. If you have docs tiled in one docksite/region then clicking anywhere on the tab or document area activates its viewmodel; however, this doesn't seem to be the case when clicking across docksites/regions. I'm not sure if this is an "across-regions" or an "across-docksites" issue.
2. Two docksites, one region.
    Only one docksite can associate with the region. So, all viewmodels must be added to the docksite assigned to the main region and then moved from this main docksite to the other docksite. I'm not sure how I would perform the "move" operation. Is it the viewmodel that I move? For reference, the docksite is populated using view injection: regionManager.Regions["MainRegion"].Add(viewModel). The "move" operation would need to maintain the viewmodel's connection to the region so that the commands/IActiveAware setup still works
Do you have any advice on how I should proceed? Perhaps there is another approach that I haven't considered?

Comments (6)

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Tony,

I don't believe #2 would work. You would have to create a distinct region for each DockSite, as in your #1. In that case, each DockSite would be independent with regards to the active windows.

Sorry, I'm not sure what the best route would be to achieve what you want, as I don't believe that is built into Prism to "union" regions in that manner.


Actipro Software Support

Posted 7 years ago by Tony Pulokas
Avatar
Since I only want there to ever be one active window, I think it makes sense to abandon the two-region approach. I'm now exploring a single region, single docksite setup that seems to satisfy my requirements:

    1. There is never more than one active window.

    2. Documents fall into one of two categories, and upon their dynamic addition to the docksite they should be moved to the correct "default" location according to their category.
I've been referring to the "Programmatic Layout" Product Sample; however, I need to be able to dock new documents with more specificity than what is detailed in the sample.

In xaml I've set up two named, empty TabbedMdiContainers, and in my code-behind the document iterates through all of the tabbed mdi containers (using MoveToNextContainer()) until it finds the container with the proper name for that type of document. At that point the document is located at the correct "default" location.

My concern is that I've come across forum threads that indicate that this setup is not a good one because:

    1. "You should never put in an empty TabbedMdiContainer in the XAML" -- http://www.actiprosoftware.com/support/forums/viewforumtopic.aspx?forumtopicid=3338

    2. "containers are transient" -- http://www.actiprosoftware.com/support/forums/viewforumtopic.aspx?forumtopicid=3819

    3. "At run-time, yes closing the last document removes the MDI container that was there. MDI containers (same with split containers and tool window containers) are dynamically created and destroyed as needed." -- http://www.actiprosoftware.com/support/forums/viewforumtopic.aspx?forumtopicid=3305
Currently, I add documents to a prism region linked to a docksite, and it seems that the documents are always added to the container that held the previously active window. This is fine by me; however, after the document is added I would like to be able to move it to its correct "default" location.

If my named, empty tabbed mdi container approach is not suitable, is there a recommended approach? Thanks!
Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Tony,

That is correct, you should not give the TabbedMdiContainers names like that as they may be removed when they are not needed any more.

Instead, you'd need to examine the open documents (i.e. DockSite.DocumentWindows or DockSite.Documents). If there is an open document of the same "type", then you can add the DocumentWindow to the same container (which is accessible via the DockingWindow.ParentContainer property).

If there isn't a document open of the same type, you'd need to see if there is an open document of the other type. If there is, is then you'd need to dock it to the left/right as needed. If not, then you'd just open it in the MDI area.


Actipro Software Support

Posted 7 years ago by Tony Pulokas
Avatar
Thanks for the suggestion, this is working great! I use the VisualTreeHelperExtended's GetAllDescendants method to find all of the ToolWindowContainers, and then apply some logic to determine which is the one I want to dock to.

I am now attempting to set the control size of the destination toolwindow container using the Docksite.SetControlSize method as is discussed in the Lifecycle and Docking Management documentation topic. Essentially, I need to set the initial size of all new toolwindows because the default width is too narrow. I have tried setting the control size on the tool window container that I am preparing to dock to:

DockSite.SetControlSize(destination, new Size(500, 500)); // destination is an existing ToolWindowContainer
activeToolWindow.Dock(destination, Direction.ContentBottom);
I have also tried setting the control size on the tool window, which is done in the Programmatic Layout QuickStart:

DockSite.SetControlSize(activeToolWindow, new Size(500, 500));
activeToolWindow.Dock(destination, Direction.ContentBottom);
Neither of these options work. I have read about the SplitContainer.ResizeSlots method, but sizing based on ratios is not the desired behavior.

To complicate matters, the toolwindow rearrangement and (hopefully) resizing code is run in response to a "DocumentAdded" event that I publish in my Prism region module after I add and activate a new viewmodel (which results in the addition of a window to the docksite). This is why I can't set the inital control size in XAML. Also my code is not responsible for the initial ToolWindow creation and addition to the Docksite (I'm guessing this happens somewhere in the Docking-Prism Interop?), so I'm not sure where I need to call the SetControlSize method to ensure it takes effect.

What are my options for setting the control size on these dynamically created toolwindows? The default size is just too narrow.
Posted 7 years ago by Tony Pulokas
Avatar
Update: I'm pretty sure I've got a solution. By the time my "DocumentAdded" event is fired I think it is too late to set the control size since the ToolWindow has already been docked to some ToolWindowContainer; however, I should have been using the DockSite Events to begin with (See: the documentation page "Docking Window Events").

I can set the control size on the ToolWindow to whatever I would like when the DockSite.WindowOpening event is published... and this works!

In the code behind for the control containing the docksite:

public MainControl()
{
    InitializeComponent();
    this.MainDockSite.WindowOpening += new EventHandler<DockingWindowEventArgs>(OnDockSiteWindowOpening);
    ...
}

private void OnDockSiteWindowOpening(object sender, DockingWindowEventArgs e)
{
    ToolWindow activeToolWindow = e.Window as ToolWindow;

    if (activeToolWindow != null)
    {
        DockSite.SetControlSize(activeToolWindow, new Size(450, 350));
    }
}
Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Tony,

That's correct, the ControlSize only works if it is set before a window/container is shown in the DockSite. In both cases, it looked like you were adding to a ToolWindowContainer that already exists, so the only method for resizing is using the SplitContainer.ResizeSlots method at that point.

Glad you got it working though.


Actipro Software Support

The latest build of this product (v2018.1 build 0675) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.