Always dock new ToolWindow to any window docked on right/left

Docking/MDI for WPF Forum

Posted 4 years ago by Shawn Kendrot
Version: 15.1.0623
Avatar

I'm creating ToolWindows in code and I'd like to always dock the window to whatever window is currently docked to the right. If no window is docked to the right then it should dock itself to the right by itself. The ToolWindow.Dock method provides a way to dock the window to another window (IDockTarget). In this case I want it to dock to whatever window is currently docked on the right. This could be window A or window B.

Comments (16)

Answer - Posted 4 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Shawn,

To find an existing open tool window target, you could see if the DockSite's child is a SplitContainer and look to see if the Orientation of it is Horizontal.  If so, look for a ToolWindowContainer as the last child and use that as a target.

Alternatively, you could iterate the DockSite.ToolWindows, looking only at open ones (IsOpen = true) in Docked state, and then check the result of their GetDirectionRelativeToWorkspace methods.  If one is on the Right, target that one.

By the way, in the upcoming major updates for vNext, we have a DefaultDockSide property that you can set.  When you open a tool window via Open() or setting IsOpen=true, it will look for an existing tool window rooted on that side and if found, will attach it to that.  That will make situations like this easier.


Actipro Software Support

Posted 4 years ago by Shawn Kendrot
Avatar

Thanks! I'll give those a shot. I keep hearing about "vNext". When will this be released?!

Posted 4 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

It should be in the next couple months or so.  Check our blog for details on major features and plans.


Actipro Software Support

Posted 4 years ago by Shawn Kendrot
Avatar

Sweet. Hopefully you'll add a public IEnumerator to DockSite.ToolWindows as well so I can access the Windows with a foreach statement.

Update: Nevermind! I just needed to add another reference

[Modified 4 years ago]

Posted 3 years ago by Shawn Kendrot
Avatar

Hello,

I was wondering how this might be accomplished if windows were opened, and then closed.

Eample:
Open window 1
Close window 1
Open window 2
Open window 1

Window 1 and 2 will not be docked together. I'm using the below code

        private void DockWindow(ToolWindow toolWindow, Direction direction)
        {
            if (direction == Direction.None)
            {
                toolWindow.Float();
                return;
            }

            bool docked = false;
            foreach (var window in DockSite.ToolWindows)
            {
                if (window.IsOpen && window.GetDirectionRelativeToWorkspace() == direction)
                {
                    toolWindow.Dock(window, Direction.Content);
                    docked = true;
                    break;
                }
            }
            if (docked == false)
            {
                toolWindow.Dock(DockSite, direction);
            }
        }

The `docked` variable will be false at the end of the method because the window is not open and the GetDirectionRelativeToWorkspace method return None.

Posted 3 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Shawn,

Have you tried upgrading to the new 2016.1 version and using the DefaultDockSide property to see if it helps, instead of specifying a docking direction?


Actipro Software Support

Posted 3 years ago by Shawn Kendrot
Avatar

I saw that it was added. I have downloaded the new bits but have not tried upgrading yet. I was hoping there might be a way to do this before we upgraded.

Posted 3 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Shawn,

If you'd like us to debug it, please make a new simple sample project showing the issue and send that over in a ZIP with a renamed .zip file extension so it doesn't get spam blocked.  Then we can see if there's a way around the problem.  Glancing at your method, it looks ok.  Thanks!


Actipro Software Support

Posted 3 years ago by Shawn Kendrot
Avatar

I put a sample online. Click the 'New Window' button. This will create new windows and dock them to the right. Close the window and open another new window. Use the dropdown and select the first window and click the "Open" button. This window wil not be docked with the other.

Posted 3 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Shawn,

The problem is that in this scenario, both tool windows end up docking to the right side of the DockSite, making their own container.  When you click the Open button later, it's just doing an Activate and returning to its prior location in the first container that was created, which is separate from the second tool window's container.

You can work around this if you copy your 'foreach' loop from the New button click handler and put that same kind of logic in the Open button click handler before the Activate() call.


Actipro Software Support

Posted 3 years ago by Shawn Kendrot
Avatar

Thank you, however I do not see a way to get te previous dock location. The `GetDirectionRelativeToWorkspace` method always returns `None` when the window is not active.

The windows shouldn't always go to the right. Some windows may dock to the right and some may dock to the left. Or if a window was moved from left to right and then closed, other windows docking to the right should be docked with it.

[Modified 3 years ago]

Posted 3 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

In the 2016.1 version, we have WindowGroupName you can assign where a newly opened window will have an attach affinity with any other already-open windows with the same WindowGroupName.  That takes priority over the DefaultDockSide too in 2016.1.  That being said, the scenario of opening a window, moving it to another location, closing it, and opening another in the same WindowGroupName likely won't dock to the same container as the original since I believe WindowGroupName only examines open documents.  Still it's a good improvement over 2015.1.

If you are wanting to stay with 2015.1, then you'd have to write logic to do something similar by examining other open windows for some that are meant to be together.  The GetDirectionRelativeToWorkspace method in 2015.1 can only give you a result if the docking window is currently open.


Actipro Software Support

Posted 3 years ago by Shawn Kendrot
Avatar

Hello,

I updated to the latest controls and tried setting the WindowGrupName property but the senerio described above still causes the first window and second window to not be docked.

Posted 3 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Yes that is sort of expected due to the explanation in our last reply.  I wonder if we should update the logic to also look at windows that have left breadcrumbs (from when they were previously open).  What do you think about that?  It would probably get this particular scenario working how you want without extra work on your end.

The only weird thing with that change is this scenario... You open TW #1 with default dock right and a certain window group name, then drag/dock it from the right down to the bottom and close it.  Then you open TW #2 that also has default dock right and the same window group name.  It would initially appear on the bottom since the breadcrumb for closed TW #1 in the same group is there.  Not sure how good or bad that is but that would be a side effect of that kind of code change on our end.

Whereas with the current codebase, TW #2 would open on the right.


Actipro Software Support

Posted 3 years ago by Shawn Kendrot
Avatar

I think ithe second window should be opened on the right regardless of if the first window was moved and closed. I tried finding a way to handle this myself by hooking into the dragged and opened events to check where the window last was, what the dockhost/site was. I found that DockHost was always the same instance if docked right or left. With the removal of docking as Content and now can only dock right/left/top/bottom there doesn't appear to be any way to handle this. Ideally I would be able to do something like (even better if it was handled by the Activate method):

private void DockWindow(ToolWindow newWindow)
{
    foreach(var window in MyDockSite.ToolWindows)
    {
        if(GetLastLocation(window) == newWindow.DefaultDockSide)
        {
            // docks as "Content" as previous version allowed
            newWindow.Dock(GetPreviousContainer(window)); 
            return;
        }
    }
    // Fallback if we did not find any place to dock
    newWindow.Activate();
}

// Gets the last Side that the window was docked.
private Side GetLastLocation(ToolWindow window);

// Returns the container for where the window last was
private IDockTarget GetPreviousContainer(ToolWindow window);

[Modified 3 years ago]

Posted 3 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Shawn,

The Dock as "content" is now a separate new Attach method.


Actipro Software Support

The latest build of this product (v2019.1 build 0681) 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.