如何使 WPF 窗口位于我的应用程序的所有其他窗口之上(不是系统范围)?

发布于 2024-08-27 02:42:34 字数 99 浏览 8 评论 0原文

我希望我的窗口位于仅在我的应用程序中的所有其他窗口之上。如果我设置窗口的 TopMost 属性,它就会位于所有应用程序的所有窗口之上,但我不希望这样。

I want my window to be on top of all other windows in my application only. If I set the TopMost property of a window, it becomes on top of all windows of all applications and I don't want that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(20

北笙凉宸 2024-09-03 02:42:34

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

您可以通过 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();
    }
  }
}

You need to set the owner property of the window.

You can show a window via showdialog in order to block your main window, or you can show it normal and have it ontop of the owner without blocking the owner.

here is a codeexample of the codebehind part - I left out all obvious stuff:

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();
    }
  }
}
萧瑟寒风 2024-09-03 02:42:34

相反,您可以使用始终位于 TopMost 的 Popup,将其装饰为类似于窗口,并将其完全附加到您的应用程序中,处理主窗口的 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();
    }

希望它有帮助!

Instead you can use a Popup that will be TopMost always, decorate it similar to a Window and to attach it completely with your Application handle the LocationChanged event of your main Window and set IsOpen property of Popup to false.

Edit:

I hope you want something like this:

    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();
    }

Hope it helps!!!

泼猴你往哪里跑 2024-09-03 02:42:34
CustomWindow cw = new CustomWindow();

cw.Owner = Application.Current.MainWindow;

cw.ShowInTaskbar = false;

cw.ShowDialog() ; 
CustomWindow cw = new CustomWindow();

cw.Owner = Application.Current.MainWindow;

cw.ShowInTaskbar = false;

cw.ShowDialog() ; 
秋千易 2024-09-03 02:42:34

XAML中很容易做到这一点,令人惊讶的是还没有人发布这个答案。在以下示例中,WindowResourceLibrary 中定义(请注意 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>

Simple to do it in XAML, and surprised that nobody posted this answer yet. In the following example, the Window is defined in a ResourceLibrary (notice the x:Key), but you can also use this XAML binding on a standalone Page-style WPF resource.

<Window x:Key="other_window" 
        Topmost="{Binding Source={x:Static Application.Current},Path=MainWindow.IsActive,Mode=OneWay}">
    <TextBlock Text="OTHER WINDOW" />
</Window>
芯好空 2024-09-03 02:42:34

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

use the Activate() method. This attempts to bring the window to the foreground and activate it.
e.g. Window wnd = new xyz();
wnd.Activate();

枫以 2024-09-03 02:42:34

在弹出窗口中,使用参数重载方法 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)

In the popup window, overloads the method Show() with a parameter:

Public Overloads Sub Show(Caller As Window)
    Me.Owner = Caller
    MyBase.Show()
End Sub

Then in the Main window, call your overloaded method Show():

Dim Popup As PopupWindow

Popup = New PopupWindow
Popup.Show(Me)
べ繥欢鉨o。 2024-09-03 02:42:34

我遇到了和你非常相似的情况。大多数搜索 我发现我需要做的就是将我希望成为最顶层的窗口的所有者设置为主窗口或任何名为“显示”的窗口。

无论如何,我会继续发布一个对我来说效果很好的解决方案。

我在窗口中为 Window.Activated 和 Window.Deactived 创建了事件处理程序,该窗口应该位于我的应用程序的最顶层。

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)

I ran into a very similar situation as you. Most of the searches I came across stated all I needed to do was set the Owner of the windows I wish to be Topmost to the main window or whatever window that called Show.

Anyways, I'll go ahead and post a solution that worked well for me.

I created event handlers for Window.Activated and Window.Deactived in the window that was supposed to be Topmost with respect to my application.

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;
}

It works great for me. Hopefully this is useful to someone else out there. :o)

尽揽少女心 2024-09-03 02:42:34

最好的方法是将这两个事件设置为应用程序的所有窗口:

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;
}
  • 当然,您想要成为顶部的所有窗口都应该可以从应用程序的其他窗口访问。
    就我而言,我有一个基本窗口和另一个应该位于基本窗口顶部的窗口,因此这对于我的基本窗口具有每个其他窗口的实例来说并不坏。

The best way is set this two events to all of windows of your app:

GotKeyboardFocus
LostKeyboardFocus

in this way:

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

WiondowOfMyApp_LostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
    windowThatShouldBeTopMost.TopMost = false;
}
  • and surely all of the windows that you wanted to be top, should be accessible from other windows of your app.
    in my case I have a base window and another some windows that should be top of my base window, so this was not bad to my base window has instance of each another windows.
养猫人 2024-09-03 02:42:34

有几个线程,甚至还有一个“最顶层”标签。搜索一下,或者直接转到这篇看起来不错的文章:

如何仅将窗口保留在我的应用程序中所有其他窗口之上?

There are several threads, there's even a "topmost" tag. Search on that, or go directly to this post which looks good:

How to keep a window on top of all other windows in my application only?

安静被遗忘 2024-09-03 02:42:34

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

不,没有办法完全做到这一点。

I'm the OP. After some research and testing, the answer is:

No, there is no way to do exactly that.

尹雨沫 2024-09-03 02:42:34

有一种方法可以做到这一点:让您的“最顶层”窗口订阅其他窗口的 GotFocus 和 LostFocus 事件,并使用以下内容作为事件处理程序:

class TopMostWindow
{
    void OtherWindow_LostFocus(object sender, EventArgs e)
    {
        this.Topmost = false;
    }

    void OtherWindow_GotFocus(object sender, EventArgs e)
    {
        this.Topmost = true;
    }
}

Here's a way to do it: make your "topmost" window subscribe to your other windows GotFocus and LostFocus events and use the following as the event handlers:

class TopMostWindow
{
    void OtherWindow_LostFocus(object sender, EventArgs e)
    {
        this.Topmost = false;
    }

    void OtherWindow_GotFocus(object sender, EventArgs e)
    {
        this.Topmost = true;
    }
}
冰之心 2024-09-03 02:42:34

您可以将其添加到您的 Windows 标签中

WindowStartupLocation="CenterScreen"

然后,如果您希望用户确认它以便继续,您也可以显示它。

YourWindow.ShowDialog();

首先尝试不使用 TopMost 参数并查看结果。

You can add this to your windows tags

WindowStartupLocation="CenterScreen"

Then you can also display it if you want your users to acknowledge it in order to proceed

YourWindow.ShowDialog();

First try it without TopMost parameters and see the results.

睡美人的小仙女 2024-09-03 02:42:34

试试这个:

Popup.PlacementTarget = sender as UIElement;

Try this:

Popup.PlacementTarget = sender as UIElement;
你怎么敢 2024-09-03 02:42:34

怎么样:

Private Sub ArrangeWindows(Order As Window())
    For I As Integer = 1 To Order.Length -1
        Order(I).Owner = Order(I - 1)
    Next
End Sub

How about htis:

Private Sub ArrangeWindows(Order As Window())
    For I As Integer = 1 To Order.Length -1
        Order(I).Owner = Order(I - 1)
    Next
End Sub
翻了热茶 2024-09-03 02:42:34

我也遇到了同样的问题,并跟随谷歌解决了这个问题。最近我发现以下内容对我有用。

CustomWindow cw = new CustomWindow();
cw.Owner = this;
cw.ShowDialog();

I too faced the same problem and followed Google to this question. Recently I found the following worked for me.

CustomWindow cw = new CustomWindow();
cw.Owner = this;
cw.ShowDialog();
逆光飞翔i 2024-09-03 02:42:34

我刚刚遇到了同样的问题。我有一个具有多个 WPF 窗口的桌面应用程序,并且我只需要将自定义启动屏幕置于应用程序中其他窗口的顶部。当我的启动屏幕出现时,没有其他窗口打开,但经过一些身份验证后,我确实从启动屏幕打开了主窗口。所以我只是做了一些类似于 @GlenSlayden 所做的事情,但在代码后面,因为就像我说的那样,主窗口不适合我绑定到:

private void SplashScreen_ContentRendered(object sender, EventArgs e)
{
    // User authentication...
    // ...

    MainWindow mainWindow = new MainWindow();
    SetBinding(SplashScreen.TopmostProperty, new Binding("IsVisible"))
    {
        Source = mainWindow,
        Mode = BindingMode.OneWay,
        UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
    };
    mainWindow.Show();
}

现在,当我的程序正在从主窗口加载所有其他窗口时,启动屏幕位于顶部,但是当程序对用户进行身份验证时,它不是最顶部的,因此您可以单击其他程序,它会隐藏在其后面。这是我能找到的最接近解决这个问题的方法。它并不完美,因为当我的程序在身份验证后加载时,它仍然超越所有其他应用程序,但就我而言,这种情况不会持续很长时间。

I just ran into this same issue. I have a desktop app that has multiple WPF windows, and I needed my custom splash screen to be on top of the other windows in my app only. No other windows are open when my splash screen comes up, but I do open the MainWindow from my splash screen after some authentication. So I just did something similar to what @GlenSlayden did but in code behind since, like I said, the MainWindow isn't up for me to bind to:

private void SplashScreen_ContentRendered(object sender, EventArgs e)
{
    // User authentication...
    // ...

    MainWindow mainWindow = new MainWindow();
    SetBinding(SplashScreen.TopmostProperty, new Binding("IsVisible"))
    {
        Source = mainWindow,
        Mode = BindingMode.OneWay,
        UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
    };
    mainWindow.Show();
}

Now while my program is loading all the other windows from the MainWindow, the splash screen is on top, but while the program is authenticating the user, it's not topmost, so you can click away on some other program and it will hide behind it. It's the closest thing I could find to a solution for this problem. It's not perfect because it still goes over top of all other applications while my program is loading after authentication, but that's not for very long in my case.

中性美 2024-09-03 02:42:34

我刚刚遇到了同样的问题,发现使用 MVVM 设置所有者时遇到了麻烦,而不会导致应用程序在生产中崩溃。我有一个窗口管理器视图模型,其中包含使用窗口的 uri 打开窗口的命令 - 并且我无法将所有者设置为 App.MainWindow 而不导致应用程序崩溃。

因此,我没有设置所有者,而是将窗口的 TopMost 属性绑定到窗口管理器视图模型中的一个属性,该属性指示应用程序当前是否处于活动状态。如果应用程序处于活动状态,窗口将按照我的意愿位于顶部。如果它不活动,其他窗口可以覆盖它。

这是我添加到视图模型中的内容:

 public class WindowManagerVM : GalaSoft.MvvmLight.ViewModelBase
    {
        public WindowManagerVM()
        {
            App.Current.Activated += (s, e) => IsAppActive = true;
            App.Current.Deactivated += (s, e) => IsAppActive = false;
        }

        private bool _isAppActive = true;
        public bool IsAppActive
        {
            get => _isAppActive;
            set
            {
                if (_isAppActive != value)
                {
                    _isAppActive = value;
                    RaisePropertyChanged(() => IsAppActive);
                }
            }
        }
    }

这是实现它的 XAML(我使用 MVVM light 和 ViewModelLocator 作为我的应用程序中名为 Locator 的静态资源):

<Window Topmost="{Binding WindowManager.IsAppActive, Source={StaticResource Locator}}"/>

I just ran into the same problem and found trouble setting the owner using MVVM without causing the app to crash in production. I have a Window Manager View Model that includes a command to open a window using the uri of the window - and I wasn't able to set the owner to App.MainWindow without the app crashing.

So - Instead of setting the owner, I bound the TopMost property of the window to a property in my Window Manager View model which indicates whether the application is currently active. If the application is active, the window is on top as I would like. If it is not active, other windows can cover it.

Here is what I added to my View Model:

 public class WindowManagerVM : GalaSoft.MvvmLight.ViewModelBase
    {
        public WindowManagerVM()
        {
            App.Current.Activated += (s, e) => IsAppActive = true;
            App.Current.Deactivated += (s, e) => IsAppActive = false;
        }

        private bool _isAppActive = true;
        public bool IsAppActive
        {
            get => _isAppActive;
            set
            {
                if (_isAppActive != value)
                {
                    _isAppActive = value;
                    RaisePropertyChanged(() => IsAppActive);
                }
            }
        }
    }

Here is the XAML that implements it (I use MVVM light with a ViewModelLocator as a static resource in my app called Locator):

<Window Topmost="{Binding WindowManager.IsAppActive, Source={StaticResource Locator}}"/>
北风几吹夏 2024-09-03 02:42:34

这对我有帮助:

Window selector = new Window ();
selector.Show();
selector.Activate();
selector.Topmost = true;

This is what helped me:

Window selector = new Window ();
selector.Show();
selector.Activate();
selector.Topmost = true;
守护在此方 2024-09-03 02:42:34

这是我对这个问题的第二个回答;我发现了另一种非常有效的技术,用于管理属于单个 Application 的多个 Window 实例

正如许多人所指出的,Window.Owner 属性是关键。每当您的应用处于活动状态(即其中一个窗口 IsActive)时,您都希望所有窗口的 Owner 属性为 null。这允许在应用程序中的各个窗口之间进行平等的切换。

但是,当您的应用处于活动状态时,您需要为每个<代码>Window.Owner 属性code>MainWindow 窗口设置为您的 MainWindow。这样,您就可以使用任何应用程序的窗口来重新激活,并且您的所有应用程序的窗口都将在所有其他应用程序之前恢复。

每次重新激活应用程序时,将 Window.Owner 值切换回 nullApplication.OnActivatedApplication.OnDeactivated 方法非常适合此目的。

您必须单独保留所有窗口的列表,因为使用此解决方法意味着您将无法在 MainWindow 上方便地使用 Window.OwnedWindows 属性,当需要执行这些调整时。

public partial class MyApp : Application
{
    // not shown: keep this list of all your non-main windows updated...
    public List<Window> rgw = new List<Window>();

    protected override void OnActivated(EventArgs e)
    {
        // when app is ACTIVE, set all `Owner` values to null...
        rgw.ForEach(w => w.Owner = null);

        base.OnActivated(e);
    }

    protected override void OnDeactivated(EventArgs e)
    {
        // set `Owner` on all non-main Windows only when not-active
        rgw.ForEach(w => w.Owner = Current.MainWindow);  

        base.OnDeactivated(e);
    }

    // etc..
}

This is my second answer to the question; I have found another very effective technique for managing multiple Window instances belonging to a single Application

As many have noted, the Window.Owner property is key. Whenever your app is active--meaning one of its windows IsActive--you want the Owner property of all your windows to be null. This allows equal switching between the various windows in your app.

But when your app is not active, you want the Window.Owner property for each of your non-MainWindow windows to be set to your MainWindow. This way, you can use any of your app's windows to re-activate, and all your app's windows will be restored in front of all other apps.

Each time the app is re-activated, switch the Window.Owner values back to null. the Application.OnActivated and Application.OnDeactivated methods are perfect for this.

You'll have to separately keep a list of all your windows, since using this workaround means you won't have the convenience of the Window.OwnedWindows property on your MainWindow, for when it comes time to perform these adjustments.

public partial class MyApp : Application
{
    // not shown: keep this list of all your non-main windows updated...
    public List<Window> rgw = new List<Window>();

    protected override void OnActivated(EventArgs e)
    {
        // when app is ACTIVE, set all `Owner` values to null...
        rgw.ForEach(w => w.Owner = null);

        base.OnActivated(e);
    }

    protected override void OnDeactivated(EventArgs e)
    {
        // set `Owner` on all non-main Windows only when not-active
        rgw.ForEach(w => w.Owner = Current.MainWindow);  

        base.OnDeactivated(e);
    }

    // etc..
}
墨离汐 2024-09-03 02:42:34

刚学C#,也遇到过类似的情况。但找到了一个我认为可能有帮助的解决方案。你可能很久以前就想到了这一点。这将来自开始一个新项目,但您可以在任何项目中使用它。

1)开始新项目。

2) 转到“项目”,然后“新建 Windows 窗体”,然后选择“Windows 窗体”并命名为“Splash”。

3)根据需要设置大小、背景、文本等。

4) 在 Splash.cs 表单的属性下设置 Start Position: CenterScreen 和 TopMost: true

5) form1 添加“using System.Threading;”

6)form1类下添加“Splash flashscreen = new Splash();”

7) form1 添加“splashscreen.Show();”和“Application.DoEvents();”

8)form1在Events>>Focus>>Activated下添加“Thread.Sleep(4000);splashscreen.Close();”

9) Splash.cs 在“Public Splash”下添加“this.BackColor = Color.Aqua;” /可以使用任何颜色

10) 这是 Form1.cs 的代码

public partial class Form1 : Form
{
    Splash splashscreen = new Splash();
    public Form1()
    {
        InitializeComponent();
        splashscreen.Show();
        Application.DoEvents();

    }

    private void Form1_Activated(object sender, EventArgs e)
    {
        Thread.Sleep(4000);
        splashscreen.Close();
    }
}

11) 这是 Splash.cs 上的代码

public partial class Splash : Form
{
    public Splash()
    {
        InitializeComponent();
        this.BackColor = Color.Aqua;
    }
}

12) 我发现如果你不在启动画面中执行某些操作,那么屏幕将不会停留在顶部第一个表单需要激活的时间。
线程计数将在 x 秒后消失,因此您的程序正常。

Just learning C# and ran across similar situation. but found a solution that I think may help. You may have figured this a long time ago. this will be from starting a new project but you can use it in any.

1) Start new project.

2) go to Project, then New Windows form, then select Windows Form and name Splash.

3) set size, background, text, etc as desired.

4) Under Properties of the Splash.cs form set Start Position: CenterScreen and TopMost: true

5) form1 add "using System.Threading;"

6) form1 under class add "Splash splashscreen = new Splash();"

7) form1 add "splashscreen.Show();" and "Application.DoEvents();"

8) form1 Under Events>>Focus>>Activated add "Thread.Sleep(4000); splashscreen.Close();"

9) Splash.cs add under "Public Splash" add "this.BackColor = Color.Aqua;" /can use any color

10) This is the code for Form1.cs

public partial class Form1 : Form
{
    Splash splashscreen = new Splash();
    public Form1()
    {
        InitializeComponent();
        splashscreen.Show();
        Application.DoEvents();

    }

    private void Form1_Activated(object sender, EventArgs e)
    {
        Thread.Sleep(4000);
        splashscreen.Close();
    }
}

11) this is the code on Splash.cs

public partial class Splash : Form
{
    public Splash()
    {
        InitializeComponent();
        this.BackColor = Color.Aqua;
    }
}

12) I found that if you do NOT do something in the splash then the screen will not stay on the top for the time the first form needs to activate.
The Thread count will disappear the splash after x seconds, so your program is normal.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文