This project is read-only.

DockingManager can't be used in an Auto sized Column

Nov 4, 2009 at 5:46 PM
Edited Nov 4, 2009 at 5:48 PM

First of all, thanks for creating a great library and providing it for free.  So far I'm enjoying working with it, and it definitely fills an important need.

It appears that DockingManager can't be fully utilized when it is contained within an Auto-sized Column.  Here is some sample Xaml code demonstrating the problem:

 <Window x:Class="WPFExperiments.AvalonDockTest6MeasuringIssues"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"
    Title="AvalonDockTest6MeasuringIssues" Height="300" Width="300">
    <Grid Background="Yellow">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <ad:DockingManager>
            <ad:ResizingPanel>
                <ad:DockablePane>
                    <ad:DockableContent Title="Test Header">
                        <TextBlock Background="Green" Foreground="White">Test</TextBlock>
                    </ad:DockableContent>
                </ad:DockablePane>
            </ad:ResizingPanel>
        </ad:DockingManager>
    </Grid>
</Window>

The DockableContent displays, and you can click the pushpin to undock it.  The anchor tab displays (vertically) on the Left, as expected.  However, the flyout window doesn't appear when you hover over or click on the tab. 

The specific reason this occurs can be found in DocumentManager::UpdateFlyoutWindowPosition.  You set the MaxWidth of the flyout window to the ActualWidth of the DockingManager.  In this case, because the DockingManager is auto-sized, its ActualWidth is the same as the width of the tab panel (approximately 22 pixels in aero).  That means the MaxWidth of the flyout window is always set to 0.  Here's the code that does that:

_flyoutWindow.MaxWidth = ActualWidth - leftTabsWidth;

My main question is whether there is some reason why I shouldn't expect to be able to use DockingManager in this way.  I need to, because my ultimate goal is to use DockingManager in a more complex layout, where the column (or row) containing DockingManager "collapses" when I undock the contents, thus allowing other parts of the layout to make use of that space.  If I were to set a specific width for DockingManager or use some other value for ColumnDefinition.Width, I wouldn't be able to achieve that effect.

My initial thought is that setting MaxWidth there would seem to be unnecessary.  In this specific case, the application works as expected when MaxWidth isn't set.  However, if you change ColumnDefinition.Width to *, the flyout window does extend beyond the edge of the application window's usable area (by what I would guess is the width of the anchor tab panel), so I can see why setting MaxWidth would be necessary in other cases. 

With that in mind, I could see a couple of options.  One is to only set MaxWidth if DockingManager.ActualWidth > leftTabsWidth; essentially, that would be like saying "if I believe the DockingManager has been auto-sized, don't worry about MaxWidth".  The other option is to set MaxWidth (and MaxHeight in other cases) based on the boundaries of the application window, if that is the "bad condition" you're trying to avoid by setting MaxWidth.

What do you think?

Thanks,

David Cater

Nov 5, 2009 at 12:03 PM
Hi David,
AvalonDock should be used to organize all the contents of your window just like happens in Visual Studio. If you want to fit it only on a portion of it (and I admit I can't understand way) you need at least add a DocumentPane just to give it the spaces for documents. Of course flyout panes will occupy only the space reserved for the DockingManager. If no documents nor flyout contents are present it will have an empty size.
You have at least set a minimum width for the column containing the dock manager or set it to '*'.
Maybe you should consider to redesign the layout of the window or use AvalonDock along with a regions manager like PRISM.
Ado

From: [email removed]
Sent: Wednesday, November 04, 2009 6:46 PM
Subject: DockingManager can't be used in an Auto sized Column [AvalonDock:74074]

From: xiard

First of all, thanks for creating a great library and providing it for free. So far I'm enjoying working with it, and it definitely fills an important need.

It appears that DockingManager can't be fully utilized when it is contained within an Auto-sized Column. Here is some sample Xaml code demonstrating the problem:

<Window x:Class="WPFExperiments.AvalonDockTest6MeasureingIssues"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"
Title="AvalonDockTest6MeasureingIssues" Height="300" Width="300">
<Grid Background="Yellow">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ad:DockingManager>
<ad:ResizingPanel>
<ad:DockablePane>
<ad:DockableContent Title="Test Header">
<TextBlock Background="Green" Foreground="White">Test</TextBlock>
</ad:DockableContent>
</ad:DockablePane>
</ad:ResizingPanel>
</ad:DockingManager>
</Grid>
</Window>

The DockableContent displays, and you can click the pushpin to undock it. The anchor tab displays (vertically) on the Left, as expected. However, the flyout window doesn't appear when you hover over or click on the tab.

The specific reason this occurs can be found in DocumentManager::UpdateFlyoutWindowPosition. You set the MaxWidth of the flyout window to the ActualWidth of the DockingManager. In this case, because the DockingManager is auto-sized, its ActualWidth is the same as the width of the tab panel (approximately 22 pixels in aero). That means the MaxWidth of the flyout window is always set to 0. Here's the code that does that:

_flyoutWindow.MaxWidth = ActualWidth - leftTabsWidth;

My main question is whether there is some reason why I shouldn't expect to be able to use DockingManager in this way. I need to, because my ultimate goal is to use DockingManager in a more complex layout, where the column (or row) containing DockingManager "collapses" when I undock the contents, thus allowing other parts of the layout to make use of that space. If I were to set a specific width for DockingManager or use some other value for ColumnDefinition.Width, I wouldn't be able to achieve that effect.

My initial thought is that setting MaxWidth there would seem to be unnecessary. In this specific case, the application works as expected when MaxWidth isn't set. However, if you change ColumnDefinition.Width to *, the flyout window does extend beyond the edge of the window (by what I would guess is the width of the anchor tab panel), so I can see why setting MaxWidth would be necessary in other cases.

With that in mind, I could see a couple of options. One is to only set MaxWidth if DockingManager.ActualWidth > leftTabsWidth; essentially, that would be like saying "if I believe the DockingManager has been auto-sized, don't worry about MaxWidth". The other option is to set MaxWidth (and MaxHeight in other cases) based on the boundaries of the application window, if that is the "bad condition" you're trying to avoid by setting MaxWidth.

What do you think?

Thanks,

David Cater

Nov 5, 2009 at 7:26 PM
Edited Nov 5, 2009 at 7:29 PM
adospace wrote:
Hi David,
AvalonDock should be used to organize all the contents of your window just like happens in Visual Studio. If you want to fit it only on a portion of it (and I admit I can't understand way) you need at least add a DocumentPane just to give it the spaces for documents. Of course flyout panes will occupy only the space reserved for the DockingManager. If no documents nor flyout contents are present it will have an empty size.
You have at least set a minimum width for the column containing the dock manager or set it to '*'.
Maybe you should consider to redesign the layout of the window or use AvalonDock along with a regions manager like PRISM.
Ado

Ado,

Thanks for the reply.  I am indeed doing something different than a Visual Studio-like layout.  The UI for our application has a simplified docking mechanism for less technical users.  You can think of it as a framework for hosting "gadgets", where there are particular slots on the page where a gadget can be dropped.  In addition, there is a "navigation bar" on the left-hand side of the page that has a button for each gadget the user has added to their application. 

We have two main goals:

1) Allow the user to "unpin" the navigation bar so it shrinks down (autohide).

2) Support a tabbed interface (a complete DockingManager) within a gadget slot so that within that slot the user can have multiple windows and advanced docking functionality.

I have created a sample project that contains both sample pages demonstrating the kind of layout I'm talking about as well as a modified version of the AvalonDock.dll.  If you're interested, you can download it from http://www.mediafire.com/?zzzdin21yby .

Here are two screenshots showing a sample layout with two DockingManagers, one to the left and one at the top in "slot #1":

Here is a list of the changes I made to the AvalonDock source code.  One of the areas I spent a bit of time on was the tab items you see in DockableTabPanel (the ones that used TextTrimming to show ellipses).  The measurement code was causing the titles to be shrunk too small, causing ellipses to show up when they didn't need to.  I believe the measurement/arrangement code (particularly the interaction between ResizingPanel and DockableTabPanel) is more correct now.  I also modified DockablePaneAnchorTabGroup to use code similar to DockableTabPanel to get the same affect (automatic TextTrimming when the tab group gets too narrow for the titles, rather than having them cut off to the right).

Changes:

  • DockableContent.cs - debug statements only
  • DockablePane.cs - debug statements only
  • DockablePaneAnchorTab.cs - debug statements only
  • DockablePaneAnchorTabGroup.cs - changed to derive from Panel and use measure/arrange code similar to DockableTabPanel to shrink tab titles down and add ellipses.
  • DockableTabPanel.cs - modified MeasureOverride to return the desired size of the panel rather than base.MeasureOverride.  Added debug statements.
  • DockingManager.cs - changed AnchorTabPanel PARTs to be DockPanel instead of StackPanel (to avoid infinite measurement issue).  Changed code that sets flyout window MaxHeight/Width to not do so if it appears the DockingManager was auto-sized.
  • ResizingPanel.cs - Modified MeasureOverride code that resizes children after determining a new availableSize to use the original height passed into the function when the Orientation is Horizontal and the original width when the Orientation is Vertical.
  • Resources\DockingManagerStyles.xaml - Modified DockablePaneAnchorTab style to use a Grid instead of StackPanel to avoid infinite measurement issues and added text trimming to the Title TextBlock.  Modified the AnchorTabPanel PARTs in DockingManager to be DockPanels instead of StackPanels to avoid infinite measurement issues.
  • themes\aero.normalcolor.xaml - Removed Horizontal orientation setter from DockableAnchorTabGroup default style because I changed it to a DockPanel.  Added TextTrimming to the Title TextBlock in the style for DockablePaneAnchorTab.
  • themes\classic.xaml - Removed Horizontal orientation setter from DockableAnchorTabGroup default style because I changed it to a DockPanel.  Added TextTrimming to the Title TextBlock in the style for DockablePaneAnchorTab.

Thanks again for all of your hard work.

David Cater

Nov 9, 2009 at 10:23 AM

Hi xiard,

it would be great if you posted source code or uploaded the patch.

Thanks,

Dragan

Nov 9, 2009 at 10:24 AM

I totally agree with ujfa!

You should post your changes so everyone benefits.

thanks

Nov 9, 2009 at 11:55 AM

See my reply above; the uploaded source code is at the mediafire link.

David