diff --git a/docfx/articles/dock-dockable-properties.md b/docfx/articles/dock-dockable-properties.md
index 80e1e3805..fa336a0f2 100644
--- a/docfx/articles/dock-dockable-properties.md
+++ b/docfx/articles/dock-dockable-properties.md
@@ -32,6 +32,7 @@ Dockable items such as documents, tools and docks implement the `IDockable` inte
| `CanFloat` | Controls if the item may be detached into a floating window. |
| `CanDrag` | Enables dragging the dockable to another position. |
| `CanDrop` | Determines if other dockables can be dropped onto this one. |
+| `CanDockAsDocument` | Controls whether the dockable can be docked as a tabbed document. |
| `IsModified` | Marks a dockable as having unsaved changes. |
| `DockGroup` | Group identifier that restricts which dockables can dock together. See [Docking Groups](dock-docking-groups.md). |
diff --git a/docfx/articles/dock-faq.md b/docfx/articles/dock-faq.md
index 97db9d9e6..d8255cb96 100644
--- a/docfx/articles/dock-faq.md
+++ b/docfx/articles/dock-faq.md
@@ -225,6 +225,13 @@ you.
Dockables may still be floated programmatically unless their `CanFloat` property
is set to `false`.
+To prevent a dockable from being docked into document docks (including the
+"Dock as Tabbed Document" command), set `CanDockAsDocument` to `false`:
+
+```csharp
+tool.CanDockAsDocument = false;
+```
+
**How can I prevent certain dockables from docking together?**
Use docking groups to control which dockables can dock together. Set the `DockGroup` property on your dockables:
diff --git a/src/Dock.Avalonia.Diagnostics/Controls/DockableDebugView.axaml b/src/Dock.Avalonia.Diagnostics/Controls/DockableDebugView.axaml
index 209fd130c..12617241a 100644
--- a/src/Dock.Avalonia.Diagnostics/Controls/DockableDebugView.axaml
+++ b/src/Dock.Avalonia.Diagnostics/Controls/DockableDebugView.axaml
@@ -4,7 +4,7 @@
x:Class="Dock.Avalonia.Diagnostics.Controls.DockableDebugView"
x:DataType="core:IDockable"
x:CompileBindings="True">
-
@@ -58,7 +58,9 @@
-
-
+
+
+
+
diff --git a/src/Dock.Avalonia.Themes.Fluent/Controls/ToolChromeControl.axaml b/src/Dock.Avalonia.Themes.Fluent/Controls/ToolChromeControl.axaml
index c42a8dd4f..36d7d8945 100644
--- a/src/Dock.Avalonia.Themes.Fluent/Controls/ToolChromeControl.axaml
+++ b/src/Dock.Avalonia.Themes.Fluent/Controls/ToolChromeControl.axaml
@@ -30,8 +30,14 @@
IsVisible="{Binding ActiveDockable.CanPin, FallbackValue=False}"/>
+ CommandParameter="{Binding ActiveDockable}">
+
+
+
+
+
+
+
+ CommandParameter="{Binding}">
+
+
+
+
+
+
+
CanDropProperty =
AvaloniaProperty.RegisterDirect(nameof(CanDrop), o => o.CanDrop, (o, v) => o.CanDrop = v);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly DirectProperty CanDockAsDocumentProperty =
+ AvaloniaProperty.RegisterDirect(nameof(CanDockAsDocument), o => o.CanDockAsDocument, (o, v) => o.CanDockAsDocument = v);
+
///
/// Defines the property.
///
@@ -228,6 +234,7 @@ public abstract class DockableBase : ReactiveBase, IDockable, IDockSelectorInfo
private bool _canFloat = true;
private bool _canDrag = true;
private bool _canDrop = true;
+ private bool _canDockAsDocument = true;
private double _minWidth = double.NaN;
private double _maxWidth = double.NaN;
private double _minHeight = double.NaN;
@@ -481,6 +488,15 @@ public bool CanDrop
set => SetAndRaise(CanDropProperty, ref _canDrop, value);
}
+ ///
+ [DataMember(IsRequired = false, EmitDefaultValue = true)]
+ [JsonPropertyName("CanDockAsDocument")]
+ public bool CanDockAsDocument
+ {
+ get => _canDockAsDocument;
+ set => SetAndRaise(CanDockAsDocumentProperty, ref _canDockAsDocument, value);
+ }
+
///
[DataMember(IsRequired = false, EmitDefaultValue = true)]
[JsonPropertyName("IsModified")]
diff --git a/src/Dock.Model.Avalonia/Json/AvaloniaDockSerializer.cs b/src/Dock.Model.Avalonia/Json/AvaloniaDockSerializer.cs
index aab0e238c..bfdb11649 100644
--- a/src/Dock.Model.Avalonia/Json/AvaloniaDockSerializer.cs
+++ b/src/Dock.Model.Avalonia/Json/AvaloniaDockSerializer.cs
@@ -63,6 +63,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
},
[typeof(IDocument)] = new List
{
@@ -78,6 +79,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
},
[typeof(IDocumentContent)] = new List
{
@@ -93,6 +95,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
},
[typeof(ITool)] = new List
{
@@ -108,6 +111,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
},
[typeof(IToolContent)] = new List
{
@@ -123,6 +127,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
},
[typeof(IDock)] = new List
{
@@ -138,6 +143,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -164,6 +170,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -192,6 +199,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -220,6 +228,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -246,6 +255,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -274,6 +284,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -300,6 +311,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -335,6 +347,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -366,6 +379,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
},
[typeof(DockBase)] = new List
{
@@ -381,6 +395,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -407,6 +422,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
},
[typeof(Tool)] = new List
{
@@ -422,6 +438,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
},
[typeof(DockDock)] = new List
{
@@ -437,6 +454,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -465,6 +483,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -493,6 +512,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -521,6 +541,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -546,6 +567,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
@@ -581,6 +603,7 @@ public AvaloniaDockSerializer()
"CanFloat",
"CanDrag",
"CanDrop",
+ "CanDockAsDocument",
// IDock
"VisibleDockables",
"ActiveDockable",
diff --git a/src/Dock.Model.CaliburMicro/Core/DockableBase.cs b/src/Dock.Model.CaliburMicro/Core/DockableBase.cs
index 34304e9e2..036ce8410 100644
--- a/src/Dock.Model.CaliburMicro/Core/DockableBase.cs
+++ b/src/Dock.Model.CaliburMicro/Core/DockableBase.cs
@@ -38,6 +38,7 @@ public abstract class DockableBase : CaliburMicroBase, IDockable, IDockSelectorI
private bool _canFloat = true;
private bool _canDrag = true;
private bool _canDrop = true;
+ private bool _canDockAsDocument = true;
private bool _isModified;
private string? _dockGroup;
private bool _showInSelector = true;
@@ -259,6 +260,14 @@ public bool CanDrop
set => Set(ref _canDrop, value);
}
+ ///
+ [DataMember(IsRequired = false, EmitDefaultValue = true)]
+ public bool CanDockAsDocument
+ {
+ get => _canDockAsDocument;
+ set => Set(ref _canDockAsDocument, value);
+ }
+
///
[DataMember(IsRequired = false, EmitDefaultValue = true)]
public bool IsModified
diff --git a/src/Dock.Model.Inpc/Core/DockableBase.cs b/src/Dock.Model.Inpc/Core/DockableBase.cs
index 0fd603275..19f505bf5 100644
--- a/src/Dock.Model.Inpc/Core/DockableBase.cs
+++ b/src/Dock.Model.Inpc/Core/DockableBase.cs
@@ -35,6 +35,7 @@ public abstract class DockableBase : ReactiveBase, IDockable, IDockSelectorInfo
private bool _canFloat = true;
private bool _canDrag = true;
private bool _canDrop = true;
+ private bool _canDockAsDocument = true;
private double _minWidth = double.NaN;
private double _maxWidth = double.NaN;
private double _minHeight = double.NaN;
@@ -260,6 +261,14 @@ public bool CanDrop
set => SetProperty(ref _canDrop, value);
}
+ ///
+ [DataMember(IsRequired = false, EmitDefaultValue = true)]
+ public bool CanDockAsDocument
+ {
+ get => _canDockAsDocument;
+ set => SetProperty(ref _canDockAsDocument, value);
+ }
+
///
[DataMember(IsRequired = false, EmitDefaultValue = true)]
public bool IsModified
diff --git a/src/Dock.Model.Mvvm/Core/DockableBase.cs b/src/Dock.Model.Mvvm/Core/DockableBase.cs
index b865b71b2..b41d18b5e 100644
--- a/src/Dock.Model.Mvvm/Core/DockableBase.cs
+++ b/src/Dock.Model.Mvvm/Core/DockableBase.cs
@@ -34,6 +34,7 @@ public abstract class DockableBase : ReactiveBase, IDockable, IDockSelectorInfo
private bool _canFloat = true;
private bool _canDrag = true;
private bool _canDrop = true;
+ private bool _canDockAsDocument = true;
private double _minWidth = double.NaN;
private double _maxWidth = double.NaN;
private double _minHeight = double.NaN;
@@ -260,6 +261,14 @@ public bool CanDrop
set => SetProperty(ref _canDrop, value);
}
+ ///
+ [DataMember(IsRequired = false, EmitDefaultValue = true)]
+ public bool CanDockAsDocument
+ {
+ get => _canDockAsDocument;
+ set => SetProperty(ref _canDockAsDocument, value);
+ }
+
///
[DataMember(IsRequired = false, EmitDefaultValue = true)]
public bool IsModified
diff --git a/src/Dock.Model.Prism/Core/DockableBase.cs b/src/Dock.Model.Prism/Core/DockableBase.cs
index 86a761c55..8deeafa69 100644
--- a/src/Dock.Model.Prism/Core/DockableBase.cs
+++ b/src/Dock.Model.Prism/Core/DockableBase.cs
@@ -34,6 +34,7 @@ public abstract class DockableBase : ReactiveBase, IDockable, IDockSelectorInfo
private bool _canFloat = true;
private bool _canDrag = true;
private bool _canDrop = true;
+ private bool _canDockAsDocument = true;
private double _minWidth = double.NaN;
private double _maxWidth = double.NaN;
private double _minHeight = double.NaN;
@@ -260,6 +261,14 @@ public bool CanDrop
set => SetProperty(ref _canDrop, value);
}
+ ///
+ [DataMember(IsRequired = false, EmitDefaultValue = true)]
+ public bool CanDockAsDocument
+ {
+ get => _canDockAsDocument;
+ set => SetProperty(ref _canDockAsDocument, value);
+ }
+
///
[DataMember(IsRequired = false, EmitDefaultValue = true)]
public bool IsModified
diff --git a/src/Dock.Model.ReactiveProperty/Core/DockableBase.cs b/src/Dock.Model.ReactiveProperty/Core/DockableBase.cs
index 72c86e02c..193919355 100644
--- a/src/Dock.Model.ReactiveProperty/Core/DockableBase.cs
+++ b/src/Dock.Model.ReactiveProperty/Core/DockableBase.cs
@@ -35,6 +35,7 @@ public abstract class DockableBase : ReactiveBase, IDockable, IDockSelectorInfo
private bool _canFloat = true;
private bool _canDrag = true;
private bool _canDrop = true;
+ private bool _canDockAsDocument = true;
private double _minWidth = double.NaN;
private double _maxWidth = double.NaN;
private double _minHeight = double.NaN;
@@ -260,6 +261,14 @@ public bool CanDrop
set => SetProperty(ref _canDrop, value);
}
+ ///
+ [DataMember(IsRequired = false, EmitDefaultValue = true)]
+ public bool CanDockAsDocument
+ {
+ get => _canDockAsDocument;
+ set => SetProperty(ref _canDockAsDocument, value);
+ }
+
///
[DataMember(IsRequired = false, EmitDefaultValue = true)]
public bool IsModified
diff --git a/src/Dock.Model.ReactiveUI/Core/DockableBase.cs b/src/Dock.Model.ReactiveUI/Core/DockableBase.cs
index 3334021d4..118388d71 100644
--- a/src/Dock.Model.ReactiveUI/Core/DockableBase.cs
+++ b/src/Dock.Model.ReactiveUI/Core/DockableBase.cs
@@ -35,6 +35,7 @@ protected DockableBase()
_canFloat = true;
_canDrag = true;
_canDrop = true;
+ _canDockAsDocument = true;
_minWidth = double.NaN;
_maxWidth = double.NaN;
_minHeight = double.NaN;
@@ -176,6 +177,11 @@ protected DockableBase()
[Reactive]
public partial bool CanDrop { get; set; }
+ ///
+ [DataMember(IsRequired = false, EmitDefaultValue = true)]
+ [Reactive]
+ public partial bool CanDockAsDocument { get; set; }
+
///
[DataMember(IsRequired = false, EmitDefaultValue = true)]
[Reactive]
diff --git a/src/Dock.Model/Core/IDockable.cs b/src/Dock.Model/Core/IDockable.cs
index d59921849..6b2df89d2 100644
--- a/src/Dock.Model/Core/IDockable.cs
+++ b/src/Dock.Model/Core/IDockable.cs
@@ -140,6 +140,11 @@ public interface IDockable : IControlRecyclingIdProvider
///
bool CanDrop { get; set; }
+ ///
+ /// Gets or sets if the dockable can be docked as a document.
+ ///
+ bool CanDockAsDocument { get; set; }
+
///
/// Gets or sets whether the dockable has unsaved changes.
///
diff --git a/src/Dock.Model/DockManager.cs b/src/Dock.Model/DockManager.cs
index 8d7f26570..6c23bd1b4 100644
--- a/src/Dock.Model/DockManager.cs
+++ b/src/Dock.Model/DockManager.cs
@@ -56,6 +56,16 @@ private static bool HasSizeConflict(ITool a, ITool b)
return widthConflict || heightConflict;
}
+ private static bool AllowsDocumentDocking(IDockable sourceDockable, IDockable targetDockable)
+ {
+ if (sourceDockable.CanDockAsDocument)
+ {
+ return true;
+ }
+
+ return targetDockable is not IDocumentDock && targetDockable is not IDocument;
+ }
+
private bool DockDockable(IDockable sourceDockable, IDock sourceDockableOwner, IDock targetDock, DockOperation operation, bool bExecute)
@@ -225,6 +235,11 @@ public bool ValidateTool(ITool sourceTool, IDockable targetDockable, DragAction
return false;
}
+ if (!AllowsDocumentDocking(sourceTool, targetDockable))
+ {
+ return false;
+ }
+
return targetDockable switch
{
IRootDock rootDock => DockDockableIntoRoot(sourceTool, rootDock, action, operation, bExecute),
@@ -399,6 +414,11 @@ public bool ValidateDocument(IDocument sourceDocument, IDockable targetDockable,
return false;
}
+ if (!AllowsDocumentDocking(sourceDocument, targetDockable))
+ {
+ return false;
+ }
+
if (targetDockable is ITool or IToolDock)
{
return false;
@@ -422,6 +442,11 @@ public bool ValidateDock(IDock sourceDock, IDockable targetDockable, DragAction
return false;
}
+ if (!AllowsDocumentDocking(sourceDock, targetDockable))
+ {
+ return false;
+ }
+
return targetDockable switch
{
IRootDock _ => _dockService.DockDockableIntoWindow(sourceDock, targetDockable, ScreenPosition, bExecute),
diff --git a/src/Dock.Model/FactoryBase.Dockable.cs b/src/Dock.Model/FactoryBase.Dockable.cs
index e4fc27f52..154d990b4 100644
--- a/src/Dock.Model/FactoryBase.Dockable.cs
+++ b/src/Dock.Model/FactoryBase.Dockable.cs
@@ -1065,6 +1065,11 @@ public virtual void FloatAllDockables(IDockable dockable)
///
public virtual void DockAsDocument(IDockable dockable)
{
+ if (!dockable.CanDockAsDocument)
+ {
+ return;
+ }
+
if (dockable.Owner is not IDock sourceDock)
{
return;
diff --git a/src/Dock.Model/FluentExtensions.cs b/src/Dock.Model/FluentExtensions.cs
index 824540037..1dcc1d9ca 100644
--- a/src/Dock.Model/FluentExtensions.cs
+++ b/src/Dock.Model/FluentExtensions.cs
@@ -593,6 +593,14 @@ private static IList EnsureList(IList? list)
/// The same instance for chaining.
public static T WithCanDrop(this T dockable, bool value) where T : IDockable { dockable.CanDrop = value; return dockable; }
///
+ /// Sets the flag.
+ ///
+ /// Dockable type.
+ /// The instance to configure.
+ /// Whether it can be docked as a document.
+ /// The same instance for chaining.
+ public static T WithCanDockAsDocument(this T dockable, bool value) where T : IDockable { dockable.CanDockAsDocument = value; return dockable; }
+ ///
/// Sets the flag.
///
/// Dockable type.
diff --git a/tests/Dock.Avalonia.HeadlessTests/DockManagerDocumentTests.cs b/tests/Dock.Avalonia.HeadlessTests/DockManagerDocumentTests.cs
index d4615e91c..f1414c140 100644
--- a/tests/Dock.Avalonia.HeadlessTests/DockManagerDocumentTests.cs
+++ b/tests/Dock.Avalonia.HeadlessTests/DockManagerDocumentTests.cs
@@ -33,6 +33,20 @@ public void ValidateDocument_ReturnsFalse_When_TargetCannotDrop()
Assert.False(result);
}
+ [AvaloniaFact]
+ public void ValidateDocument_ReturnsFalse_When_SourceCannotDockAsDocument_And_TargetIsDocumentDock()
+ {
+ var manager = new DockManager(new DockService());
+ var sourceDock = new DocumentDock { VisibleDockables = new AvaloniaList() };
+ var source = new Document { Owner = sourceDock, CanDockAsDocument = false };
+ sourceDock.VisibleDockables!.Add(source);
+ var target = new DocumentDock { VisibleDockables = new AvaloniaList(), CanDrop = true };
+
+ var result = manager.ValidateDocument(source, target, DragAction.Move, DockOperation.Fill, false);
+
+ Assert.False(result);
+ }
+
[AvaloniaFact]
public void IsDockTargetVisible_ReturnsFalse_For_Same_Dockable()
{
diff --git a/tests/Dock.Avalonia.HeadlessTests/DockManagerTests.cs b/tests/Dock.Avalonia.HeadlessTests/DockManagerTests.cs
index 2176a89f6..1ed011e6f 100644
--- a/tests/Dock.Avalonia.HeadlessTests/DockManagerTests.cs
+++ b/tests/Dock.Avalonia.HeadlessTests/DockManagerTests.cs
@@ -54,4 +54,32 @@ public void ValidateTool_ReturnsTrue_When_Valid()
var result = manager.ValidateTool(tool, targetDock, DragAction.Move, DockOperation.Fill, false);
Assert.True(result);
}
+
+ [AvaloniaFact]
+ public void ValidateTool_ReturnsFalse_When_SourceCannotDockAsDocument_And_TargetIsDocumentDock()
+ {
+ var manager = new DockManager(new DockService());
+ var sourceDock = new ToolDock { VisibleDockables = new AvaloniaList() };
+ var tool = new Tool { Owner = sourceDock, CanDockAsDocument = false };
+ sourceDock.VisibleDockables!.Add(tool);
+ var targetDock = new DocumentDock { VisibleDockables = new AvaloniaList(), CanDrop = true };
+
+ var result = manager.ValidateTool(tool, targetDock, DragAction.Move, DockOperation.Fill, false);
+
+ Assert.False(result);
+ }
+
+ [AvaloniaFact]
+ public void ValidateTool_ReturnsTrue_When_SourceCanDockAsDocument_And_TargetIsDocumentDock()
+ {
+ var manager = new DockManager(new DockService());
+ var sourceDock = new ToolDock { VisibleDockables = new AvaloniaList() };
+ var tool = new Tool { Owner = sourceDock, CanDockAsDocument = true };
+ sourceDock.VisibleDockables!.Add(tool);
+ var targetDock = new DocumentDock { VisibleDockables = new AvaloniaList(), CanDrop = true };
+
+ var result = manager.ValidateTool(tool, targetDock, DragAction.Move, DockOperation.Fill, false);
+
+ Assert.True(result);
+ }
}
diff --git a/tests/Dock.Avalonia.HeadlessTests/FactoryDockAsDocumentTests.cs b/tests/Dock.Avalonia.HeadlessTests/FactoryDockAsDocumentTests.cs
new file mode 100644
index 000000000..f8b901418
--- /dev/null
+++ b/tests/Dock.Avalonia.HeadlessTests/FactoryDockAsDocumentTests.cs
@@ -0,0 +1,32 @@
+using Avalonia.Headless.XUnit;
+using Dock.Model.Avalonia;
+using Dock.Model.Avalonia.Controls;
+using Dock.Model.Core;
+using Xunit;
+
+namespace Dock.Avalonia.HeadlessTests;
+
+public class FactoryDockAsDocumentTests
+{
+ [AvaloniaFact]
+ public void DockAsDocument_DoesNothing_When_DockableCannotDockAsDocument()
+ {
+ var factory = new Factory();
+ var root = new RootDock { VisibleDockables = factory.CreateList() };
+ root.Factory = factory;
+
+ var documentDock = new DocumentDock { VisibleDockables = factory.CreateList() };
+ var toolDock = new ToolDock { VisibleDockables = factory.CreateList() };
+
+ factory.AddDockable(root, documentDock);
+ factory.AddDockable(root, toolDock);
+
+ var tool = new Tool { CanDockAsDocument = false };
+ factory.AddDockable(toolDock, tool);
+
+ factory.DockAsDocument(tool);
+
+ Assert.Same(toolDock, tool.Owner);
+ Assert.DoesNotContain(tool, documentDock.VisibleDockables!);
+ }
+}
diff --git a/tests/Dock.Model.UnitTests/DockGroupValidationTests.cs b/tests/Dock.Model.UnitTests/DockGroupValidationTests.cs
index 37f455876..c21d3f001 100644
--- a/tests/Dock.Model.UnitTests/DockGroupValidationTests.cs
+++ b/tests/Dock.Model.UnitTests/DockGroupValidationTests.cs
@@ -35,6 +35,7 @@ private class SimpleDockable : IDockable
public bool CanFloat { get; set; } = true;
public bool CanDrag { get; set; } = true;
public bool CanDrop { get; set; } = true;
+ public bool CanDockAsDocument { get; set; } = true;
public bool IsModified { get; set; }
public string? DockGroup { get; set; }
public IFactory? Factory { get; set; }