Error in DockingManager.RefreshContents when using nested DockingManagers?

Jul 13, 2010 at 1:50 PM

Dear All,

There appears to be a problem within AvalonDock when using nested DockingManagers.

I have a Main window that contains a DockingManager,  "dmA". The dmA contains several child DockableContent objects. Each child DockableContent has its own DockingManager, "dmB", which each have two child DockableContents. All of this is read in by XAMLReader dynamically at run time.

When I call RestoreLayout, the child DockableContents of all the dmB objects are removed. I have diagnosed the problem as follows:

 

I think the fault is between DockingManager.RefreshContents and ILinqToTreeExts.Descendants.

RefreshContents calls into Descendants which returns all all descendant ManagedContent objects, including those that are descendants of child DockingManagers. This leads to the RestoreLayout function malfunctioning and removing all ManagedContent objects from the the child DockingManagers. A solution is to block the recursion in the function ILinqToTreeExts.Descendants to prevent it from recursing through DockingManager objects. In my code, the DockPanel object is a convenient object to use for the block. I have amended the function as follows:

public static IEnumerable<ILinqToTree<T>>
Descendants<T>(this ILinqToTree<T> adapter)
{
foreach (var child in adapter.Children())
{
yield return child;

/*LKM 12/07/10
* This condition is a fudge to amend what appears to be a bug in AvalonDock (issue 11429).
* When an XAML file contains a docking manager (dm A), which constains one or more
* docking windows, which each contain their own docking manager (dm B) with child
* docking windows, then when the child ManagedContent objects are retrieved from dm A
* by calling this function, then ALL ManagedContent objects are retrieved, including those
* that belong to dm B.
*
* This suspected bug has been overcome by blocking recursion through a DockPanel. Our
* windows have a DockPanel as their root element so this should be sufficient.
*/

if (!(adapter.Item is System.Windows.Controls.DockPanel)) //LKM Fudge for 11429.
{
foreach (var grandChild in child.Descendants())
{
yield return grandChild;
}
}
}
}

Can anyone please comment on this,

Best wishes,