Reputation: 885
Is it possible to prevent docking one anchorable element to another one by using some filtering? For example, at viewmodel I can include some property doctype
. For one anchorable element the value for doctype
will be "a" and for the another one "b". How can I use property doctype
to prevent docking if anchorable element with value "a" can't docking to anchorable element with doctype
"b"? Maybe, there are other solutions for this.
Upvotes: 1
Views: 1342
Reputation: 1061
In AvalonDock 3.5 (since 3.2 I think) there is a LayoutAnchorable
property CanDockAsTabbedDocument
which can be set to false to prevent toolwindows from being docked into the DocumentPane
. This works only for the context menu in AvalonDock 3.8 and earlier while the drag&drop behavior is still buggy.
But you can use this fix to get the expected drag&drop behavior for AvalonDock 3.5.
The code below extends the IOverlayWindowHost.GetDropAreas
in DockingManager.cs
The Key to this solution is the dockAsDocument
boolean variable. It guards the foreach loop that is responsible for inserting any items into the DocumentsPane
of the MainWindow
.
The dockAsDocument
variable is set to false as soon as there is one LayoutAnchorable
(toolwindow) that can be found inside the LayoutFloatingWindowControl
and was configured with CanDockAsTabbedDocument="False"
.
IEnumerable<IDropArea> IOverlayWindowHost.GetDropAreas( LayoutFloatingWindowControl draggingWindow )
{
if( _areas != null )
return _areas;
bool isDraggingDocuments = draggingWindow.Model is LayoutDocumentFloatingWindow;
_areas = new List<IDropArea>();
if( !isDraggingDocuments )
{
_areas.Add( new DropArea<DockingManager>(
this,
DropAreaType.DockingManager ) );
foreach( var areaHost in this.FindVisualChildren<LayoutAnchorablePaneControl>() )
{
if( areaHost.Model.Descendents().Any() )
{
_areas.Add( new DropArea<LayoutAnchorablePaneControl>(
areaHost,
DropAreaType.AnchorablePane ) );
}
}
}
// Determine if floatingWindow is configured to dock as document or not
bool dockAsDocument = true;
if (isDraggingDocuments == false)
{
var toolWindow = draggingWindow.Model as LayoutAnchorableFloatingWindow;
if (toolWindow != null)
{
foreach (var item in GetAnchorableInFloatingWindow(draggingWindow))
{
if (item.CanDockAsTabbedDocument == false)
{
dockAsDocument = false;
break;
}
}
}
}
// Dock only documents and tools in DocumentPane if configuration does allow that
if (dockAsDocument == true)
{
foreach( var areaHost in this.FindVisualChildren<LayoutDocumentPaneControl>() )
{
_areas.Add( new DropArea<LayoutDocumentPaneControl>(
areaHost,
DropAreaType.DocumentPane ) );
}
}
foreach( var areaHost in this.FindVisualChildren<LayoutDocumentPaneGroupControl>() )
{
var documentGroupModel = areaHost.Model as LayoutDocumentPaneGroup;
if( documentGroupModel.Children.Where( c => c.IsVisible ).Count() == 0 )
{
_areas.Add( new DropArea<LayoutDocumentPaneGroupControl>(
areaHost,
DropAreaType.DocumentPaneGroup ) );
}
}
return _areas;
}
/// <summary>
/// Finds all <see cref="LayoutAnchorable"/> objects (toolwindows) within a
/// <see cref="LayoutFloatingWindow"/> (if any) and return them.
/// </summary>
/// <param name="draggingWindow"></param>
/// <returns></returns>
private IEnumerable<LayoutAnchorable> GetAnchorableInFloatingWindow(LayoutFloatingWindowControl draggingWindow)
{
var layoutAnchorableFloatingWindow = draggingWindow.Model as LayoutAnchorableFloatingWindow;
if (layoutAnchorableFloatingWindow != null)
{
//big part of code for getting type
var layoutAnchorablePane = layoutAnchorableFloatingWindow.SinglePane as LayoutAnchorablePane;
if (layoutAnchorablePane != null
&& (layoutAnchorableFloatingWindow.IsSinglePane
&& layoutAnchorablePane.SelectedContent != null))
{
var layoutAnchorable = ((LayoutAnchorablePane)layoutAnchorableFloatingWindow.SinglePane).SelectedContent as LayoutAnchorable;
yield return layoutAnchorable;
}
else
{
foreach (var item in GetLayoutAnchorable(layoutAnchorableFloatingWindow.RootPanel))
{
yield return item;
}
}
}
}
/// <summary>
/// Finds all <see cref="LayoutAnchorable"/> objects (toolwindows) within a
/// <see cref="LayoutAnchorablePaneGroup"/> (if any) and return them.
/// </summary>
/// <param name="layoutAnchPaneGroup"></param>
/// <returns></returns>
internal IEnumerable<LayoutAnchorable> GetLayoutAnchorable(LayoutAnchorablePaneGroup layoutAnchPaneGroup)
{
if (layoutAnchPaneGroup != null)
{
foreach (var anchorable in layoutAnchPaneGroup.Descendents().OfType<LayoutAnchorable>())
{
yield return anchorable;
}
}
}
Upvotes: 1
Reputation: 1
It's correct to change IOverlayWindowHost.GetDropAreas
, but the change seems a lot easier to me.
I simple removed this foreach in "LayoutAnchorableFloatingWindowControl.cs":
...
// Remove this foreach
foreach (var areaHost in rootVisual.FindVisualChildren<LayoutDocumentPaneControl>())
{
_dropAreas.Add(new DropArea<LayoutDocumentPaneControl>(
areaHost,
DropAreaType.DocumentPane));
}
return _dropAreas;
and in the other implementation in "DockingManager.cs" you have to add an else cause:
if (!isDraggingDocuments)
{
_areas.Add(new DropArea<DockingManager>(
this,
DropAreaType.DockingManager));
foreach (var areaHost in this.FindVisualChildren<LayoutAnchorablePaneControl>())
{
if (areaHost.Model.Descendents().Any())
{
_areas.Add(new DropArea<LayoutAnchorablePaneControl>(
areaHost,
DropAreaType.AnchorablePane));
}
}
}
// -----> This else is new
else
{
foreach (var areaHost in this.FindVisualChildren<LayoutDocumentPaneControl>())
{
_areas.Add(new DropArea<LayoutDocumentPaneControl>(
areaHost,
DropAreaType.DocumentPane));
}
foreach (var areaHost in this.FindVisualChildren<LayoutDocumentPaneGroupControl>())
{
var documentGroupModel = areaHost.Model as LayoutDocumentPaneGroup;
if (documentGroupModel.Children.Where(c => c.IsVisible).Count() == 0)
{
_areas.Add(new DropArea<LayoutDocumentPaneGroupControl>(
areaHost,
DropAreaType.DocumentPaneGroup));
}
}
}
return _areas;
So, if you are not dragging an LayoutDocument, don't add the document pane controls to your drop areas.
Thats it - works for me.
Upvotes: 0
Reputation: 885
I changed IOverlayWindowHost.GetDropAreas
method at LayoutAnchorableFloatingWindowControl.cs
First step was intializing the type of content.
var floatingWindowContentHost = Content as FloatingWindowContentHost;
if (floatingWindowContentHost == null) return _dropAreas;
var rootVisual = floatingWindowContentHost.RootVisual;
Type type = null;
var layoutAnchorableFloatingWindow = draggingWindow.Model as LayoutAnchorableFloatingWindow;
if (layoutAnchorableFloatingWindow != null)
{
//big part of code for getting type
var layoutAnchorablePane = layoutAnchorableFloatingWindow.SinglePane as LayoutAnchorablePane;
if (layoutAnchorablePane != null
&& (layoutAnchorableFloatingWindow.IsSinglePane
&& layoutAnchorablePane.SelectedContent != null))
{
var layoutAnchorable = ((LayoutAnchorablePane)layoutAnchorableFloatingWindow.SinglePane).SelectedContent as LayoutAnchorable;
if (layoutAnchorable != null)
type = layoutAnchorable.Content;
}
else
{
var pane = GetLayoutAnchorablePane(layoutAnchorableFloatingWindow.RootPanel);
if (pane == null || pane.SelectedContent == null)
return null;
var layoutAnchorable = pane.SelectedContent as LayoutAnchorable;
if (layoutAnchorable != null)
type = layoutAnchorable.Content;
}
}
After this I just compare two types and put needed into _dropAreas
.
foreach (var areaHost in rootVisual.FindVisualChildren<LayoutAnchorablePaneControl>())
{
Type areahostType = null;
var layoutAnchorablePane = areaHost.Model as LayoutAnchorablePane;
if (layoutAnchorablePane != null && layoutAnchorablePane.SelectedContent != null)
{
var layoutAnchorable = ((LayoutAnchorablePane)areaHost.Model).SelectedContent as LayoutAnchorable;
if (layoutAnchorable != null)
areahostType = layoutAnchorable.Content;
}
// prevent docking different documents
if (type != null && areahostType != null && areahostType == type)
{
_dropAreas.Add(new DropArea<LayoutAnchorablePaneControl>( areaHost, DropAreaType.AnchorablePane));
}
}
For the prevent docking into document area, need to make changes for the same method at DockingManager.cs
For the visual preventing of DropTargets need to change OverlayWindow.cs
Upvotes: 0