如何使WPF窗口在我的应用程序中位于所有其他窗口的顶部(而非整个系统)?

74

我希望我的窗口在仅限于我的应用程序中处于最顶部。如果我设置窗口的TopMost属性,它将变为所有应用程序窗口的顶部,但我不想这样。


顺便说一下,我无法在那个窗口上设置Owner,因为那个窗口是在任何其他窗口之前创建的(它是应用程序启动画面)。参考:https://dev59.com/l3E95IYBdhLWcg3wGZ5_ - Sylvain
虽然这个问题已经很老了,但我还是要发表一下评论...你的问题和评论有点奇怪,你想让你的窗口在应用程序的顶部,但在你的评论中,你说没有应用程序在运行,因为它是第一个窗口(启动画面),那么你的窗口怎么能在不存在的应用程序上面呢?!?这让我想知道这个问题怎么会得到16个赞。 - Rand Random
1
当应用程序启动时,除了主窗口之外没有其他窗口出现,但主窗口很快就会出现,并且必须一直停留在启动画面后面,直到所有内容都加载完毕。 - Sylvain
1
为什么不让启动屏幕成为第一个窗口,等它完成任务后再打开主窗口呢?只需将应用程序的StartupUri更改为启动屏幕即可。(http://msdn.microsoft.com/en-us/library/system.windows.application.startupuri(v=vs.110).aspx) - Rand Random
20个回答

55

你需要设置窗口的所有者属性。

你可以通过showdialog显示一个窗口来阻止你的主窗口,或者将其正常显示并使其在所有者窗口上方而不阻塞所有者窗口。

这是代码后台部分的一个示例 - 我省略了所有明显的部分:

namespace StackoverflowExample
{
  public partial class MainWindow : Window
  {
    public MainWindow()
    {
      InitializeComponent();
    }
    void NewWindowAsDialog(object sender, RoutedEventArgs e)
    {
      Window myOwnedDialog = new Window();
      myOwnedDialog.Owner = this;
      myOwnedDialog.ShowDialog();
    }
    void NormalNewWindow(object sender, RoutedEventArgs e)
    {
      Window myOwnedWindow = new Window();
      myOwnedWindow.Owner = this;
      myOwnedWindow.Show();
    }
  }
}

2
这正是我正在寻找的——如何打开一个新窗口,直到关闭前保持焦点/活动状态。谢谢。 - N t
2
最好将 myOwnedDialog.ShowInTaskbar = false; 添加到 NewWindowAsDialog 中。 - mkb

17

你可以使用一个弹出窗口来实现始终置顶的效果,将其装饰得与窗口类似,并通过处理主窗口的LocationChanged事件完全附加到应用程序中,然后将Popup的IsOpen属性设置为false。

编辑:

我希望你想要的是这样的效果:

    Window1 window;

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        window = new Window1();
        window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
        window.Topmost = true;
        this.LocationChanged+=OnLocationchanged;
        window.Show();
    }
     
    private void OnLocationchanged(object sender, EventArgs e)
    {
          if(window!=null)
              window.Close();
    }

希望这有所帮助!!!


1
这将使窗口置于所有其他应用程序之上。那么LocationChanged处理程序的含义是什么(顺便说一句:按照C#约定,处理程序不以'On'为前缀)? - Martin Schneider

14
CustomWindow cw = new CustomWindow();

cw.Owner = Application.Current.MainWindow;

cw.ShowInTaskbar = false;

cw.ShowDialog() ; 

1
你能在代码旁边提供一些解释吗?这有助于每个人理解你的答案。 - Matt Wilko
1
如果您进行正确的窗口配置,它将按预期运行。该窗口将位于应用程序中所有其他窗口的顶部。 - Alex
对我没用,出现了“空引用异常”。我的对话框是WPF窗口,但应用程序和主窗口是WinForms。 - Colonel Panic
这将使其模态。希望次要窗口在主窗口前面,但仍能与主窗口交互。 - doobop
设置所有者后,您可以使用"仅显示(show only)"选项。然后主窗口就可以被单击了。 - Paweł Iwaneczko

12

XAML中很容易实现,令人惊讶的是还没有人发布过这个答案。在下面的示例中,Window被定义在一个ResourceLibrary中(注意x:Key),但你也可以将此XAML绑定用于独立的类似Page的WPF资源。

<Window x:Key="other_window" 
        Topmost="{Binding Source={x:Static Application.Current},Path=MainWindow.IsActive,Mode=OneWay}">
    <TextBlock Text="OTHER WINDOW" />
</Window>

简单而有效,谢谢! - undefined

5
在弹出窗口中,使用一个参数重载Show()方法:
Public Overloads Sub Show(Caller As Window)
    Me.Owner = Caller
    MyBase.Show()
End Sub

然后在主窗口中调用您重载的Show()方法:

Dim Popup As PopupWindow

Popup = New PopupWindow
Popup.Show(Me)

5

使用Activate()方法。它会尝试将窗口置于前台并激活它。 例如:Window wnd = new xyz(); wnd.Activate();


4
我遇到了与您非常相似的情况。我遇到的大多数搜索都说明,我所需要做的就是将我希望置顶的窗口的所有者设置为主窗口或调用Show的任何窗口。
无论如何,我会提供一个对我很有效的解决方案。
我在应用程序中与我的窗口相关的Window.Activated和Window.Deactivated事件处理程序中创建了一个置顶窗口。
private void Window_Activated(object sender, EventArgs e)
{
    Topmost = true;
}

private void Window_Deactived(object sender, EventArgs e)
{
    if(Owner == null || Owner.IsActive)
        return;
    bool hasActiveWindow = false;
    foreach(Window ownedWindow in Owner.OwnedWindows)
    {
        if(ownedWindow.IsActive)
            hasActiveWindow = true; 
    }

    if(!hasActiveWindow)
        Topmost = false;
}

这对我非常有效。希望这对其他人有所帮助。:o)


当我点击另一个应用程序时,我的窗口不再处于活动状态,因此Topmost永远不会被设置为false。 - Matt Zappitello
我通过在if语句中检查Topmost而不是IsActive,成功使其工作:if (ownedWindow.Topmost)... - Matt Zappitello

4
最好的方法是将这两个事件设置给您应用程序的所有窗口:
GotKeyboardFocus
LostKeyboardFocus

以这种方式:

WiondowOfMyApp_GotKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
    windowThatShouldBeTopMost.TopMost = true;
}

WiondowOfMyApp_LostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
    windowThatShouldBeTopMost.TopMost = false;
}
  • 当然,你希望置顶的所有窗口都应该可以从你的应用程序的其他窗口中访问。 在我的情况下,我有一个基础窗口和另外一些窗口,这些窗口应该位于我的基础窗口的顶部,因此我的基础窗口拥有每个其他窗口的实例并不是坏事。

这对于制作弹出窗口或实用程序窗口非常完美,当它们不活动时不会悬停在其他应用程序窗口上。谢谢! - rob_williams

2

4
这个问题是针对“Windows Forms”窗体的Windows操作系统,而我有一个WPF(Windows Presentation Foundation)窗体。 - Sylvain
1
我无法设置Owner属性,因为在我的情况下,窗口是在任何其他窗口之前创建的。因此,我没有其他窗口可以设置为所有者。 - Sylvain

2

我是楼主。经过一些研究和测试,答案是:

不,没有办法完全做到那样。


1
有方法可以做到这一点。其中一些答案是不错的选择。 - Holf
那么,请解释一下paint.net是如何制作出仅位于应用程序顶部的颜色、历史和工具箱窗口的。 - Burak Yeniçeri
@BurakYeniçeri 九年后...我不知道。当时,经过多次尝试,我得出结论认为这是不可能的。很久以后,Johannes提出了一个有很多赞的解决方案,我想这是一个好的解决方案。我已经清除了我的答案上的“接受”。 - Sylvain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接