diff --git a/source/Components/AvalonDock/Controls/DragService.cs b/source/Components/AvalonDock/Controls/DragService.cs index 8b072181..1d0da1dd 100644 --- a/source/Components/AvalonDock/Controls/DragService.cs +++ b/source/Components/AvalonDock/Controls/DragService.cs @@ -237,11 +237,25 @@ internal void Abort() #region Private Methods + /// + /// Adds s into a private collection of possible + /// drop target hosts that can show a drop target button to drop a dragged + /// or + /// into it. + /// private void GetOverlayWindowHosts() { - _overlayWindowHosts.AddRange(_manager.GetFloatingWindowsByZOrder().OfType().Where(fw => fw != _floatingWindow && fw.IsVisible)); - _overlayWindowHosts.AddRange(_manager.GetFloatingWindowsByZOrder().OfType().Where(fw => fw != _floatingWindow && fw.IsVisible)); - _overlayWindowHosts.Add(_manager); + if (_manager.Layout.RootPanel.CanDock) + { + // Add LayoutFloatingWindowControls as drop target hosts + // 1) Don't drop a floating window on to itself + // 2) Use this Drop target if its visible + _overlayWindowHosts.AddRange(_manager.GetFloatingWindowsByZOrder().OfType().Where(fw => fw != _floatingWindow && fw.IsVisible)); + _overlayWindowHosts.AddRange(_manager.GetFloatingWindowsByZOrder().OfType().Where(fw => fw != _floatingWindow && fw.IsVisible)); + + // Add dockingManager itself as a drop target host + _overlayWindowHosts.Add(_manager); + } } #endregion Private Methods diff --git a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs index ed55315f..5c6947b9 100644 --- a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs @@ -80,6 +80,9 @@ internal LayoutAnchorableFloatingWindowControl(LayoutAnchorableFloatingWindow mo #region Properties + /// + public override ILayoutElement Model => _model; + #region SingleContentLayoutItem /// dependency property. @@ -176,10 +179,6 @@ IEnumerable IOverlayWindowHost.GetDropAreas(LayoutFloatingWindowContr #endregion Public Methods #region Overrides - - /// - public override ILayoutElement Model => _model; - /// protected override void OnInitialized(EventArgs e) { diff --git a/source/Components/AvalonDock/Controls/OverlayWindow.cs b/source/Components/AvalonDock/Controls/OverlayWindow.cs index 9904d2d8..9a4d4b51 100644 --- a/source/Components/AvalonDock/Controls/OverlayWindow.cs +++ b/source/Components/AvalonDock/Controls/OverlayWindow.cs @@ -356,6 +356,7 @@ IEnumerable IOverlayWindow.GetTargets() { case DropAreaType.DockingManager: { + // Dragging over DockingManager -> Add DropTarget Area var dropAreaDockingManager = visibleArea as DropArea; yield return new DockingManagerDropTarget(dropAreaDockingManager.AreaElement, _dockingManagerDropTargetLeft.GetScreenArea(), DropTargetType.DockingManagerDockLeft); yield return new DockingManagerDropTarget(dropAreaDockingManager.AreaElement, _dockingManagerDropTargetTop.GetScreenArea(), DropTargetType.DockingManagerDockTop); @@ -365,6 +366,7 @@ IEnumerable IOverlayWindow.GetTargets() break; case DropAreaType.AnchorablePane: { + // Dragging over AnchorablePane -> Add DropTarget Area var dropAreaAnchorablePane = visibleArea as DropArea; yield return new AnchorablePaneDropTarget(dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetLeft.GetScreenArea(), DropTargetType.AnchorablePaneDockLeft); yield return new AnchorablePaneDropTarget(dropAreaAnchorablePane.AreaElement, _anchorablePaneDropTargetTop.GetScreenArea(), DropTargetType.AnchorablePaneDockTop); @@ -399,6 +401,7 @@ IEnumerable IOverlayWindow.GetTargets() break; case DropAreaType.DocumentPane: { + // Dragging over DocumentPane -> Add DropTarget Area bool isDraggingAnchorables = _floatingWindow.Model is LayoutAnchorableFloatingWindow; if (isDraggingAnchorables && _gridDocumentPaneFullDropTargets != null) { @@ -483,6 +486,7 @@ IEnumerable IOverlayWindow.GetTargets() break; case DropAreaType.DocumentPaneGroup: { + // Dragging over DocumentPaneGroup -> Add DropTarget Area var dropAreaDocumentPane = visibleArea as DropArea; if (_documentPaneDropTargetInto.IsVisible) yield return new DocumentPaneGroupDropTarget(dropAreaDocumentPane.AreaElement, _documentPaneDropTargetInto.GetScreenArea(), DropTargetType.DocumentPaneGroupDockInside); diff --git a/source/Components/AvalonDock/Layout/LayoutAnchorable.cs b/source/Components/AvalonDock/Layout/LayoutAnchorable.cs index 51002bab..335f8e57 100644 --- a/source/Components/AvalonDock/Layout/LayoutAnchorable.cs +++ b/source/Components/AvalonDock/Layout/LayoutAnchorable.cs @@ -151,7 +151,9 @@ public bool CanDockAsTabbedDocument } } - /// Gets/sets whether a document can be dragged (to be dropped in a different location) or not. Use this property in conjunction with and to lock a document in its layout position. + /// Gets/sets whether a document can be dragged (to be dropped in a different location) or not. + /// Use this property in conjunction with and and + /// to lock an anchorable in its layout position. public bool CanMove { get => _canMove; diff --git a/source/Components/AvalonDock/Layout/LayoutDocument.cs b/source/Components/AvalonDock/Layout/LayoutDocument.cs index 13114740..42579494 100644 --- a/source/Components/AvalonDock/Layout/LayoutDocument.cs +++ b/source/Components/AvalonDock/Layout/LayoutDocument.cs @@ -26,7 +26,9 @@ public class LayoutDocument : LayoutContent #region Properties - /// Gets/sets whether a document can be dragged (to be dropped in a different location) or not. Use this property in conjunction with and to lock a document in its layout position. + /// Gets/sets whether a document can be dragged (to be dropped in a different location) or not. + /// Use this property in conjunction with and and + /// to lock a document in its layout position. public bool CanMove { get => _canMove; diff --git a/source/Components/AvalonDock/Layout/LayoutPanel.cs b/source/Components/AvalonDock/Layout/LayoutPanel.cs index 3612ee37..c0a739a3 100644 --- a/source/Components/AvalonDock/Layout/LayoutPanel.cs +++ b/source/Components/AvalonDock/Layout/LayoutPanel.cs @@ -11,6 +11,7 @@ This program is provided to you under the terms of the Microsoft Public using System.Linq; using System.Windows.Markup; using System.Windows.Controls; +using System.Windows; namespace AvalonDock.Layout { @@ -52,6 +53,32 @@ public Orientation Orientation } } + #region CanDock + /// + /// Using a DependencyProperty as the backing store for thhe property. + /// + public static readonly DependencyProperty CanDockProperty = + DependencyProperty.Register("CanDock", typeof(bool), + typeof(LayoutPanel), new PropertyMetadata(true)); + + /// + /// Gets/sets dependency property that determines whether docking of dragged items + /// is enabled or not. This property can be used disable/enable docking of + /// dragged FloatingWindowControls. + /// + /// This property should only be set to false if: + /// and + /// are false since users will otherwise be able to: + /// 1) Drag an item away + /// 2) But won't be able to dock it agin. + /// + public bool CanDock + { + get { return (bool)GetValue(CanDockProperty); } + set { SetValue(CanDockProperty, value); } + } + #endregion CanDock + #endregion Properties #region Overrides @@ -63,14 +90,28 @@ public Orientation Orientation public override void WriteXml(System.Xml.XmlWriter writer) { writer.WriteAttributeString(nameof(Orientation), Orientation.ToString()); + + if (CanDock == false) + writer.WriteAttributeString(nameof(CanDock), CanDock.ToString()); + base.WriteXml(writer); } /// + /// + /// This method is never invoked - .ReadRootPanel() + /// for implementation of this reader. + /// public override void ReadXml(System.Xml.XmlReader reader) { if (reader.MoveToAttribute(nameof(Orientation))) Orientation = (Orientation)Enum.Parse(typeof(Orientation), reader.Value, true); + if (reader.MoveToAttribute(nameof(CanDock))) + { + var canDockStr = reader.GetAttribute("CanDock"); + if (canDockStr != null) + CanDock = bool.Parse(canDockStr); + } base.ReadXml(reader); } diff --git a/source/Components/AvalonDock/Layout/LayoutRoot.cs b/source/Components/AvalonDock/Layout/LayoutRoot.cs index 402cede2..c32adeb2 100644 --- a/source/Components/AvalonDock/Layout/LayoutRoot.cs +++ b/source/Components/AvalonDock/Layout/LayoutRoot.cs @@ -548,10 +548,10 @@ void IXmlSerializable.ReadXml(XmlReader reader) return; } - var layoutPanelElements = ReadRootPanel(reader, out var orientation); + var layoutPanelElements = ReadRootPanel(reader, out var orientation, out var canDock); if (layoutPanelElements != null) { - RootPanel = new LayoutPanel { Orientation = orientation }; + RootPanel = new LayoutPanel { Orientation = orientation, CanDock = canDock }; //Add all children to RootPanel foreach (var panel in layoutPanelElements) RootPanel.Children.Add(panel); } @@ -786,9 +786,20 @@ private void FillLayoutAnchorSide(XmlReader reader, LayoutAnchorSide layoutAncho } } - private List ReadRootPanel(XmlReader reader, out Orientation orientation) + /// + /// Reads all properties of the and returns them. + /// + /// + /// + /// + /// + private List ReadRootPanel(XmlReader reader + , out Orientation orientation + , out bool canDock) { orientation = Orientation.Horizontal; + canDock = true; + var result = new List(); var startElementName = reader.LocalName; reader.Read(); @@ -799,6 +810,11 @@ private List ReadRootPanel(XmlReader reader, out Orientatio if (reader.LocalName.Equals(nameof(RootPanel))) { orientation = (Orientation)Enum.Parse(typeof(Orientation),reader.GetAttribute(nameof(Orientation)), true); + + var canDockStr = reader.GetAttribute("CanDock"); + if (canDockStr != null) + canDock = bool.Parse(canDockStr); + reader.Read(); while (true) {