diff --git a/samples/DockReactiveUICanonicalSample/App.axaml b/samples/DockReactiveUICanonicalSample/App.axaml
index acc5f8ac0..88922add6 100644
--- a/samples/DockReactiveUICanonicalSample/App.axaml
+++ b/samples/DockReactiveUICanonicalSample/App.axaml
@@ -22,8 +22,9 @@
diff --git a/src/Dock.Avalonia/Controls/Overlays/OverlayHost.cs b/src/Dock.Avalonia/Controls/Overlays/OverlayHost.cs
index e75116a61..fdebb7276 100644
--- a/src/Dock.Avalonia/Controls/Overlays/OverlayHost.cs
+++ b/src/Dock.Avalonia/Controls/Overlays/OverlayHost.cs
@@ -250,6 +250,14 @@ private void OnOverlayLayerPropertyChanged(object? sender, AvaloniaPropertyChang
private void RebuildPipeline()
{
+ if (Content is Control hostedContent && hostedContent.Parent is not null)
+ {
+ if (!TryDetachControl(hostedContent))
+ {
+ return;
+ }
+ }
+
Child = null;
var contentPresenter = new ContentPresenter
@@ -268,7 +276,7 @@ private void RebuildPipeline()
continue;
}
- if (!TryDetachOverlay(overlay))
+ if (!TryDetachControl(overlay))
{
continue;
}
@@ -315,25 +323,25 @@ private void RebuildPipeline()
Child = current;
}
- private static bool TryDetachOverlay(Control overlay)
+ private static bool TryDetachControl(Control control)
{
- if (overlay.Parent is null)
+ if (control.Parent is null)
{
return true;
}
- switch (overlay.Parent)
+ switch (control.Parent)
{
case Panel panel:
- panel.Children.Remove(overlay);
+ panel.Children.Remove(control);
return true;
- case Decorator decorator when ReferenceEquals(decorator.Child, overlay):
+ case Decorator decorator when ReferenceEquals(decorator.Child, control):
decorator.Child = null;
return true;
- case ContentPresenter presenter when ReferenceEquals(presenter.Content, overlay):
+ case ContentPresenter presenter when ReferenceEquals(presenter.Content, control):
presenter.Content = null;
return true;
- case ContentControl contentControl when ReferenceEquals(contentControl.Content, overlay):
+ case ContentControl contentControl when ReferenceEquals(contentControl.Content, control):
contentControl.Content = null;
return true;
default:
diff --git a/tests/Dock.Avalonia.HeadlessTests/HostWindowThemeChangeTests.cs b/tests/Dock.Avalonia.HeadlessTests/HostWindowThemeChangeTests.cs
new file mode 100644
index 000000000..ae4a66dce
--- /dev/null
+++ b/tests/Dock.Avalonia.HeadlessTests/HostWindowThemeChangeTests.cs
@@ -0,0 +1,55 @@
+using System;
+using Avalonia;
+using Avalonia.Headless.XUnit;
+using Avalonia.Styling;
+using Dock.Avalonia.Controls;
+using Dock.Model.Avalonia;
+using Dock.Model.Controls;
+using Dock.Model.Core;
+using Xunit;
+
+namespace Dock.Avalonia.HeadlessTests;
+
+public class HostWindowThemeChangeTests
+{
+ private static IRootDock CreateLayout(Factory factory)
+ {
+ var root = factory.CreateRootDock();
+ root.Factory = factory;
+ root.VisibleDockables = factory.CreateList();
+ return root;
+ }
+
+ [AvaloniaFact]
+ public void HostWindow_ThemeChange_DoesNotDuplicate_DockControls()
+ {
+ var app = Application.Current ?? throw new InvalidOperationException("Application is not initialized.");
+ var factory = new Factory();
+ var layout = CreateLayout(factory);
+ var window = new HostWindow();
+ var originalVariant = app.RequestedThemeVariant;
+
+ try
+ {
+ window.SetLayout(layout);
+ window.Show();
+ window.UpdateLayout();
+
+ Assert.Single(factory.DockControls);
+ Assert.Same(layout, window.Content);
+
+ app.RequestedThemeVariant = ThemeVariant.Dark;
+ window.UpdateLayout();
+ Assert.Single(factory.DockControls);
+
+ app.RequestedThemeVariant = ThemeVariant.Light;
+ window.UpdateLayout();
+ Assert.Single(factory.DockControls);
+ }
+ finally
+ {
+ window.Close();
+ app.RequestedThemeVariant = originalVariant;
+ }
+ }
+}