WPF Always On Top

C#WpfTopmost

C# Problem Overview


Is it possible to make a window stay always on top even when other application is running on Fullscreen? I'm using right now TopMost = true but when other application is running on fullscreen mine becomes invisible. It's WindowStyle = None window by the way.

Edit: And do not let other window minimalize ofcourse

C# Solutions


Solution 1 - C#

This won't work 100% of the time, but it will improve the situation somewhat. You can set Topmost = true in the handler for the Window.Deactivated event:

private void Window_Deactivated(object sender, EventArgs e)
{
    Window window = (Window)sender;
    window.Topmost = true;
}

The Deactivated event will be called whenever your application loses focus (often when another application requests to be Topmost) and so this will reset your application on top after this.

Solution 2 - C#

Try this solution from MSDN, it should work for you. In the Window Activated Event add the following code:

this.Width   = System.Windows.SystemParameters.PrimaryScreenWidth;
this.Height  = System.Windows.SystemParameters.PrimaryScreenHeight;
this.Topmost = true;
this.Top  = 0;
this.Left = 0;

in DeActivated Event add the following code

this.Topmost = true;
this.Activate();

Original post from MSDN

Solution 3 - C#

None of the solutions above for me worked, so here is what I ended up doing. It worked perfectly for me.

Basically, to keep it on top you just set the lose focus event to make it go back to top.

XAML:

PreviewLostKeyboardFocus="Window_PreviewLostKeyboardFocus"
    

Code Behind:

private void Window_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
      var window = (Window)sender;
      window.Topmost = true;
}

Solution 4 - C#

So I ran into the same requirement recently. It seems the top rated answer as well as the second didn't properly work for me. I've found a solution that seems to work flawlessly and somewhat adheres to best practice using MVVM.

Using the below forces the window to the top and never lapses on change like the other solutions.

Step 1: I created a simple state manager class for my main client window. I used INotifyPropertyChanged to keep property in sync when using a direct binding to my window. (very important)

public class ClientStateManager : INotifyPropertyChanged
{
    #region Private Variables
    private bool isForceToTop;
    private bool isClientEnabled;
    #endregion

    #region Public Properties
    public bool IsForceToTop
    {
        get { return isForceToTop; }
        set
        {
            isForceToTop = value;
            NotifyPropertyChanged();
        }
    }
    public bool IsClientEnabled
    {
        get { return isClientEnabled; }
        set
        {
            isClientEnabled = value;
            NotifyPropertyChanged();
        }
    }       
    #endregion

    #region Private Methods
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion

    #region Public Methods
    public void Lock() => this.IsClientEnabled = false;
    public void UnLock() => this.IsClientEnabled = true;
    public void SetTop() => this.IsForceToTop = true;
    public void UnSetTop() => this.IsForceToTop = false;
    #endregion

    #region Public Events
    public event PropertyChangedEventHandler PropertyChanged; 
    #endregion
}

Step 2.1: Added my state manager class to my ViewModel. (MVVM)

  internal class MainWindowViewModel : INotifyPropertyChanged
  {
    #region Constructor
    public MainWindowViewModel() 
    {
        ClientStateManager = new ClientStateManager();
    }
    #endregion

    #region Public Properties  
    public ClientStateManager ClientStateManager { get; private set; }
    #endregion
  }

Step 2.2: Then set your window data context to your view model.

  private MainWindowViewModel model;
  private MainWindow()
  {
        InitializeComponent();
        this.model = new MainWindowViewModel();
        this.DataContext = model;
  }   

Step 3: Add your data binding to your window.

  <Window x:Class="Intouch_Work.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:ojects="clr-namespace:Framework.Object;assembly=Framework"
    xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"     
    mc:Ignorable="d"
    Title="Intouch" Height="800" Width="1100"
    x:Name="mainWindow"
    Topmost="{Binding Path=ClientStateManager.IsForceToTop, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">

So now you can manage your window state using the state manager object initialized within the View Model. You can call SetTop() from you state manager to push it forward, or UnSetTop() to stop it. Hope this helps anyone looking to do the same.

Solution 5 - C#

If you want your application to stay on top of EVERYTHING (including the start interface in Windows 8, previously known as "Metro"), then you can specify UiAccess="True" in your manifest file. This is typically used by accessibility applications such as onscreen keyboards.

From memory you need to do 3 things;

  1. Request UiAccess="True"
  2. Sign your application's exe file with a recognised certificate. I obtained a free code signing certificate from Certum as my project is Open Source.
  3. Install your application to a "Trusted Location", which in my case was the program files directory. There is no official definition of "Trusted Location" that I could find.

Solution 6 - C#

I had a main window that I wanted to keep on top of everything (if the user checked "always on top".
This worked for me. Hope this helps someone.

// If we want main to stay on top, we set the rest of the menus to Not be top 
if (mnuViewMainWindowAlwaysOnTopo.IsChecked)
{
    this.Topmost = true;
    
    foreach (var window in Application.Current.Windows)
        // Don't change for main window
        if (window.GetType().Name != this.GetType().Name)
            window.Topmost = false;
}
else this.Topmost = false;

Solution 7 - C#

I needed something similar for an industrial quality control application, where non-admin operators should not be able to minimize or use anything else on the dedicated computer while the application is running, not even Windows+D to bring up the desktop. And I found out that the cleanest and simplest way to achieve that is through:

  1. Settings the correct Width, Height, WindowStyle, WindowState and Topmost properties.
  2. Handling some related events: StateChanged, Deactivated, LostFocuse, LostMouseCapture, LostKeyboardFocus and PreviewLostKeyboardFocus.
  3. Handling closing events with ALT+F4 or a custom button).

No need for P/Invoke, Here is the full code:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Loaded += OnLoaded;
            Closing += OnClosing;
            StateChanged += OnStateChanged;
            Deactivated += (sender, args) => Activate();
            LostFocus += (sender, args) => Focus();
            LostMouseCapture += (sender, args) => Mouse.Capture(this);
            LostKeyboardFocus += (sender, args) => Keyboard.Focus(this);
            PreviewLostKeyboardFocus += (sender, args) => Keyboard.Focus(this);
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            Width = SystemParameters.PrimaryScreenWidth;
            Height = SystemParameters.PrimaryScreenHeight;
            WindowStyle = WindowStyle.None;
            WindowState = WindowState.Maximized;
            Topmost = true;
            // Other stuff here
        }

        private void OnClosing(object sender, CancelEventArgs e)
        {
            // You might want to allow only some users to close the app
            if (MessageBox.Show("Are you an admin?", "Admin Check", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.No)
               e.Cancel = true;
        }

        private void OnStateChanged(object sender, EventArgs e)
        {
            if (WindowState == WindowState.Minimized)
                WindowState = WindowState.Maximized;
        }
    }

You can also put some of this in XAML:

<Window x:Class="FullScreen.MainWindow"
        ...
        Title="MainWindow"
        WindowState="Maximized"
        WindowStyle="None" 
        Topmost="True">
    <Grid>
        
    </Grid>
</Window>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKuba WasilczykView Question on Stackoverflow
Solution 1 - C#SheridanView Answer on Stackoverflow
Solution 2 - C#Mohammed A. FadilView Answer on Stackoverflow
Solution 3 - C#Travis TubbsView Answer on Stackoverflow
Solution 4 - C#B.SpangenbergView Answer on Stackoverflow
Solution 5 - C#JuliusView Answer on Stackoverflow
Solution 6 - C#pStanView Answer on Stackoverflow
Solution 7 - C#HUSMENView Answer on Stackoverflow