diff --git a/src/System.Windows.Forms.Primitives/src/System/LocalAppContextSwitches/LocalAppContextSwitches.cs b/src/System.Windows.Forms.Primitives/src/System/LocalAppContextSwitches/LocalAppContextSwitches.cs
index 5b728b3472a..0e71a335aaa 100644
--- a/src/System.Windows.Forms.Primitives/src/System/LocalAppContextSwitches/LocalAppContextSwitches.cs
+++ b/src/System.Windows.Forms.Primitives/src/System/LocalAppContextSwitches/LocalAppContextSwitches.cs
@@ -26,6 +26,7 @@ internal static partial class LocalAppContextSwitches
internal const string EnableMsoComponentManagerSwitchName = "Switch.System.Windows.Forms.EnableMsoComponentManager";
internal const string TreeNodeCollectionAddRangeRespectsSortOrderSwitchName = "System.Windows.Forms.TreeNodeCollectionAddRangeRespectsSortOrder";
internal const string MoveTreeViewTextLocationOnePixelSwitchName = "System.Windows.Forms.TreeView.MoveTreeViewTextLocationOnePixel";
+ internal const string MirrorTopMostForModalDialogsSwitchName = "System.Windows.Forms.MirrorTopMostForModalDialogs";
private static int s_scaleTopLevelFormMinMaxSizeForDpi;
private static int s_anchorLayoutV2;
@@ -37,6 +38,7 @@ internal static partial class LocalAppContextSwitches
private static int s_noClientNotifications;
private static int s_enableMsoComponentManager;
private static int s_treeNodeCollectionAddRangeRespectsSortOrder;
+ private static int s_mirrorTopMostForModalDialogs;
private static int s_moveTreeViewTextLocationOnePixel;
@@ -222,6 +224,18 @@ public static bool TreeNodeCollectionAddRangeRespectsSortOrder
get => GetCachedSwitchValue(TreeNodeCollectionAddRangeRespectsSortOrderSwitchName, ref s_treeNodeCollectionAddRangeRespectsSortOrder);
}
+ ///
+ /// When true, ShowDialog will temporarily set the dialog as TopMost if its owner is TopMost.
+ /// This prevents the dialog from being covered by the owner during the modal session.
+ /// The original TopMost state is restored after closing.
+ /// Default is false. Set to true for .NET Framework-compatible behavior.
+ ///
+ public static bool MirrorTopMostForModalDialogs
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => GetCachedSwitchValue(MirrorTopMostForModalDialogsSwitchName, ref s_mirrorTopMostForModalDialogs);
+ }
+
///
/// Indicates whether to move the text position of a TreeView node one pixel
/// to the right relative to the upper-left corner of the TreeView control.
diff --git a/src/System.Windows.Forms/System/Windows/Forms/Form.cs b/src/System.Windows.Forms/System/Windows/Forms/Form.cs
index c3900d09c6b..be78adab8f0 100644
--- a/src/System.Windows.Forms/System/Windows/Forms/Form.cs
+++ b/src/System.Windows.Forms/System/Windows/Forms/Form.cs
@@ -5718,6 +5718,9 @@ public DialogResult ShowDialog(IWin32Window? owner)
Form? oldOwner = OwnerInternal;
+ bool originalTopMost = TopMost;
+ bool mirrored = false;
+
try
{
SetState(States.Modal, true);
@@ -5755,6 +5758,12 @@ public DialogResult ShowDialog(IWin32Window? owner)
if (owner is Form form && owner != oldOwner)
{
Owner = form;
+
+ if (AppContextSwitches.MirrorTopMostForModalDialogs && TopLevel && !IsMdiChild && Owner.TopMost && !TopMost)
+ {
+ TopMost = true;
+ mirrored = true;
+ }
}
else
{
@@ -5814,6 +5823,11 @@ public DialogResult ShowDialog(IWin32Window? owner)
Owner = oldOwner;
Properties.RemoveValue(s_propDialogOwner);
GC.KeepAlive(ownerHwnd.Wrapper);
+
+ if (mirrored)
+ {
+ TopMost = originalTopMost;
+ }
}
return DialogResult;