Mettre une fenêtre en avant dans WPF

215

Comment puis-je mettre mon application WPF à l'avant du bureau? Jusqu'à présent, j'ai essayé:

SwitchToThisWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle, true);

SetWindowPos(new WindowInteropHelper(Application.Current.MainWindow).Handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

SetForegroundWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle);

Aucun d'entre eux ne fait le travail ( Marshal.GetLastWin32Error()indique que ces opérations se sont terminées avec succès et que les attributs P / Invoke pour chaque définition en ont SetLastError=true).

Si je crée une nouvelle application WPF vierge et que j'appelle SwitchToThisWindowavec un minuteur, cela fonctionne exactement comme prévu, donc je ne sais pas pourquoi cela ne fonctionne pas dans mon cas d'origine.

Edit : je fais cela en conjonction avec un raccourci clavier global.

Facteur mystique
la source
Avez-vous vérifié que MainWindow est la fenêtre souhaitée? À partir de MSDN: MainWindow est automatiquement défini avec une référence au premier objet Window à instancier dans AppDomain.
Todd White
Bonne pensée, mais c'est la seule fenêtre de l'application.
Factor Mystic
Pouvez-vous donner un peu plus de code contextuel?
Todd White

Réponses:

315
myWindow.Activate();

Tente d'amener la fenêtre au premier plan et de l'activer.

Cela devrait faire l'affaire, sauf si j'ai mal compris et que vous voulez un comportement Always on Top. Dans ce cas, vous souhaitez:

myWindow.TopMost = true;
Morten Christiansen
la source
14
J'utilisais simplement myWindow.Show () et parfois ce n'était pas au top. J'ai immédiatement appelé myWindow.Activate () et cela a fonctionné.
Bermo
4
Activer ne fonctionne pas parfois sur Windows XP. Je recommande la réponse de @Matthew Xavier.
Lex Li
Un peu étrange, car par défaut ShowActivated est activé.
greenoldman
1
La première réponse est bonne, merci pour ça! Mais la deuxième ligne de code, l'utilisation de la Topmostpropriété est une mauvaise pratique car elle peut masquer d'autres boîtes de dialogue contextuelles et avoir un comportement inattendu.
Jonathan Perry
3
En fait, cela peut être fait avec ceci: if (myWindow.WindowState == WindowState.Minimized) myWindow.WindowState = WindowState.Normal;Curieusement, il préservera également toutes les fenêtres maximisées et ne les ramènera pas à un état normal.
r41n
168

J'ai trouvé une solution qui amène la fenêtre en haut, mais elle se comporte comme une fenêtre normale:

if (!Window.IsVisible)
{
    Window.Show();
}

if (Window.WindowState == WindowState.Minimized)
{
    Window.WindowState = WindowState.Normal;
}

Window.Activate();
Window.Topmost = true;  // important
Window.Topmost = false; // important
Window.Focus();         // important
Jader Dias
la source
1
Excellent indice! TopMost fait que la magie opère sur Windows 7 si la fenêtre est déjà ouverte, mais en dessous des autres fenêtres.
gsb
Cela a aussi fait l'affaire pour moi. Merci à gsb pour le commentaire supplémentaire sur ce qui ressemble à une utilisation étrange de TopMost!
Jen
1
Merci - la solution a été courte et douce.
code4life
2
Dans mon cas, Window.Activate () et Window.Focus () étaient suffisants. La définition de Window.TopMost n'est pas nécessaire.
virieux
6
Ne pas utiliser Window.Focus(). Cela détournera l'attention de ce que l'utilisateur tape actuellement dans une zone de texte, ce qui est extrêmement frustrant pour les utilisateurs finaux. Le code ci-dessus fonctionne très bien sans lui.
Contango
32

Si vous avez besoin que la fenêtre soit devant la première fois qu'elle se charge, vous devez utiliser les éléments suivants:

private void Window_ContentRendered(object sender, EventArgs e)
{
    this.Topmost = false;
}

private void Window_Initialized(object sender, EventArgs e)
{
    this.Topmost = true;
}
Amir
la source
1
Si vous développez quelque chose de similaire à Launchy ( launchy.net ) en C #, vous devriez remarquer que cette réponse est presque inutile.
Lex Li
21

Pour en faire un copier-coller rapide -
Utilisez cette DoOnProcessméthode de classe pour déplacer la fenêtre principale du processus au premier plan (mais pas pour voler le focus à partir d'autres fenêtres)

public class MoveToForeground
{
    [DllImportAttribute("User32.dll")]
    private static extern int FindWindow(String ClassName, String WindowName);

    const int SWP_NOMOVE        = 0x0002;
    const int SWP_NOSIZE        = 0x0001;            
    const int SWP_SHOWWINDOW    = 0x0040;
    const int SWP_NOACTIVATE    = 0x0010;
    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);

    public static void DoOnProcess(string processName)
    {
        var allProcs = Process.GetProcessesByName(processName);
        if (allProcs.Length > 0)
        {
            Process proc = allProcs[0];
            int hWnd = FindWindow(null, proc.MainWindowTitle.ToString());
            // Change behavior by settings the wFlags params. See http://msdn.microsoft.com/en-us/library/ms633545(VS.85).aspx
            SetWindowPos(new IntPtr(hWnd), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
        }
    }
}

HTH

Hertzel Guinness
la source
6
+1 c'est la seule réponse qui m'a été utile. J'ai une application avec un maître et plusieurs fenêtres esclaves flottantes. Lors de l'activation de l'une d'entre elles, toutes les autres fenêtres doivent également être mises en avant. Mais pas activé / gagnez le focus comme le suggèrent la plupart des réponses: c'est un désastre car cela rend la fenêtre actuellement cliquée sur unclickable car soudainement une autre fenêtre gagne le focus.
stijn
Une raison pour ne pas utiliser process.MainWindowHandle?
Sriram Sakthivel
Dans mon cas, je ne voulais pas de la fenêtre principale, mais je suis d'accord, il y a d'autres façons d'obtenir un hWnd. FWIW un HwndSourceobjet a bien fonctionné.
tobriand
21

Je sais que cette question est assez ancienne, mais je viens de tomber sur ce scénario précis et je voulais partager la solution que j'ai implémentée.

Comme mentionné dans les commentaires sur cette page, plusieurs des solutions proposées ne fonctionnent pas sur XP, que je dois prendre en charge dans mon scénario. Bien que je sois d'accord avec le sentiment de @Matthew Xavier selon lequel c'est généralement une mauvaise pratique UX, il y a des moments où c'est entièrement une UX plausable.

La solution pour amener une fenêtre WPF au sommet m'a été fournie par le même code que j'utilise pour fournir le raccourci clavier global. Un article de blog de Joseph Cooney contient un lien vers ses exemples de code qui contient le code d'origine.

J'ai nettoyé et modifié un peu le code et l'ai implémenté comme méthode d'extension à System.Windows.Window. J'ai testé cela sur XP 32 bits et Win7 64 bits, qui fonctionnent tous les deux correctement.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace System.Windows
{
    public static class SystemWindows
    {
        #region Constants

        const UInt32 SWP_NOSIZE = 0x0001;
        const UInt32 SWP_NOMOVE = 0x0002;
        const UInt32 SWP_SHOWWINDOW = 0x0040;

        #endregion

        /// <summary>
        /// Activate a window from anywhere by attaching to the foreground window
        /// </summary>
        public static void GlobalActivate(this Window w)
        {
            //Get the process ID for this window's thread
            var interopHelper = new WindowInteropHelper(w);
            var thisWindowThreadId = GetWindowThreadProcessId(interopHelper.Handle, IntPtr.Zero);

            //Get the process ID for the foreground window's thread
            var currentForegroundWindow = GetForegroundWindow();
            var currentForegroundWindowThreadId = GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero);

            //Attach this window's thread to the current window's thread
            AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true);

            //Set the window position
            SetWindowPos(interopHelper.Handle, new IntPtr(0), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);

            //Detach this window's thread from the current window's thread
            AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false);

            //Show and activate the window
            if (w.WindowState == WindowState.Minimized) w.WindowState = WindowState.Normal;
            w.Show();
            w.Activate();
        }

        #region Imports

        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

        [DllImport("user32.dll")]
        private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

        [DllImport("user32.dll")]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

        #endregion
    }
}

J'espère que ce code aide ceux qui rencontrent ce problème.

Zodman
la source
Hé, chéri! Je lutte avec ça depuis des mois! Cela fonctionne pour mes deux situations. Impressionnant! (Windows 7 x64)
mdiehl13
En fait, cela ne semble fonctionner que si je fais cela: App.mainWindow.Show (); SystemWindows.GlobalActivate (App.mainwindow); // Lorsque je supprime le premier .show (), il ne passe pas au premier plan
mdiehl13
+1 pour SetWindowPos (), je cherchais un moyen de ne mettre ma fenêtre en avant sans interrompre d'autres applications ou voler le focus. this.Activate () vole le focus.
prettyvoid
Cela l'a fait pour moi, et dans mon cas, le but était de voler le focus, car cela arrivait lorsqu'un utilisateur interagissait avec certains éléments. Merci beaucoup, cela semble fonctionner de manière cohérente! simplement appeler this.Activate()ne semble fonctionner que quelques fois.
Peter
13

Si l'utilisateur interagit avec une autre application, il peut ne pas être possible de mettre la vôtre au premier plan. En règle générale, un processus ne peut s'attendre à définir la fenêtre de premier plan que si ce processus est déjà le processus de premier plan. (Microsoft documente les restrictions dans l' entrée MSDN SetForegroundWindow () .) En effet:

  1. L'utilisateur «possède» le premier plan. Par exemple, il serait extrêmement ennuyeux si un autre programme volait le premier plan pendant que l'utilisateur tape, interrompant à tout le moins son flux de travail et pouvant entraîner des conséquences inattendues car ses frappes destinées à une application sont mal interprétées par le délinquant jusqu'à ce qu'elle remarque le changement .
  2. Imaginez que chacun des deux programmes vérifie si sa fenêtre est au premier plan et tente de le mettre au premier plan s'il ne l'est pas. Dès que le deuxième programme est en cours d'exécution, l'ordinateur est rendu inutile car le premier plan rebondit entre les deux à chaque changement de tâche.
Matthew Xavier
la source
Bon point. Le but du code était en conjonction avec un raccourci clavier global, cependant, et d'autres applications le font d'une manière ou d'une autre.
Factor Mystic
Vous devez utiliser PInvoke en C # pour émuler ce qui est décrit dans cet article, codeproject.com/Tips/76427/…
Lex Li
alors pourquoi les boîtes de dialogue contextuelles d'erreur de mélange d'expression restent visibles lorsque je passe parfois à Visual Studio? : - /
Simon_Weaver
Simon, je soupçonne que les fenêtres d'erreur que vous voyez sont des fenêtres "les plus hautes" (une décision de conception que je désapprouve). Il existe une différence entre la fenêtre de premier plan (qui reçoit les entrées de l'utilisateur) et une fenêtre "supérieure" dans l'ordre Z. N'importe quelle fenêtre peut se rendre «au sommet», ce qui la place au-dessus de toutes les fenêtres non supérieures, mais ne donne pas le focus au clavier de la fenêtre, etc. comme le fait la fenêtre de premier plan.
Matthew Xavier
L'astuce échoue pour quelques fenêtres spéciales. Visual Studio et les fenêtres d'invite de commandes doivent avoir quelque chose qui empêche toute autre fenêtre de devenir la fenêtre de premier plan.
Lex Li
9

Je sais que c'est une réponse tardive, peut-être utile pour les chercheurs

 if (!WindowName.IsVisible)
 {
     WindowName.Show();
     WindowName.Activate();
 }
Jamaxack
la source
9

Pourquoi certaines des réponses sur cette page sont fausses!

  • Toute réponse qui utilise window.Focus()est fausse.

    • Pourquoi? Si un message de notification apparaît, window.Focus()le focus s'éloignera de tout ce que l'utilisateur tape à l'époque. Cela est extrêmement frustrant pour les utilisateurs finaux, surtout si les fenêtres contextuelles apparaissent assez fréquemment.
  • Toute réponse qui utilise window.Activate()est fausse.

    • Pourquoi? Cela rendra également visibles toutes les fenêtres parentes.
  • Toute réponse qui omet window.ShowActivated = falseest fausse.
    • Pourquoi? Cela attirera l'attention hors d'une autre fenêtre lorsque le message apparaîtra, ce qui est très ennuyeux!
  • Toute réponse qui n'utilise pas Visibility.Visiblepour masquer / afficher la fenêtre est fausse.
    • Pourquoi? Si nous utilisons Citrix, si la fenêtre n'est pas réduite lorsqu'elle est fermée, cela laissera une étrange prise rectangulaire noire sur l'écran. Ainsi, nous ne pouvons pas utiliser window.Show()et window.Hide().

Essentiellement:

  • La fenêtre ne doit pas capturer le focus loin de toute autre fenêtre lorsqu'elle s'active;
  • La fenêtre ne doit pas activer son parent lorsqu'elle est affichée;
  • La fenêtre doit être compatible avec Citrix.

Solution MVVM

Ce code est 100% compatible avec Citrix (pas de zones vides de l'écran). Il est testé avec WPF normal et DevExpress.

Cette réponse est destinée à tout cas d'utilisation où nous voulons une petite fenêtre de notification qui est toujours en face des autres fenêtres (si l'utilisateur le sélectionne dans les préférences).

Si cette réponse semble plus complexe que les autres, c'est parce qu'elle est robuste, au niveau de l'entreprise. Certaines des autres réponses sur cette page sont simples, mais ne fonctionnent pas réellement.

XAML - Propriété attenante

Ajoutez cette propriété attachée à n'importe quelle UserControldans la fenêtre. La propriété attenante:

  • Attendez que l' Loadedévénement soit déclenché (sinon il ne peut pas rechercher dans l'arborescence visuelle pour trouver la fenêtre parent).
  • Ajoutez un gestionnaire d'événements qui garantit que la fenêtre est visible ou non.

À tout moment, vous pouvez définir la fenêtre devant ou non, en inversant la valeur de la propriété attachée.

<UserControl x:Class="..."
         ...
         attachedProperties:EnsureWindowInForeground.EnsureWindowInForeground=
             "{Binding EnsureWindowInForeground, Mode=OneWay}">

C # - Méthode d'assistance

public static class HideAndShowWindowHelper
{
    /// <summary>
    ///     Intent: Ensure that small notification window is on top of other windows.
    /// </summary>
    /// <param name="window"></param>
    public static void ShiftWindowIntoForeground(Window window)
    {
        try
        {
            // Prevent the window from grabbing focus away from other windows the first time is created.
            window.ShowActivated = false;

            // Do not use .Show() and .Hide() - not compatible with Citrix!
            if (window.Visibility != Visibility.Visible)
            {
                window.Visibility = Visibility.Visible;
            }

            // We can't allow the window to be maximized, as there is no de-maximize button!
            if (window.WindowState == WindowState.Maximized)
            {
                window.WindowState = WindowState.Normal;
            }

            window.Topmost = true;
        }
        catch (Exception)
        {
            // Gulp. Avoids "Cannot set visibility while window is closing".
        }
    }

    /// <summary>
    ///     Intent: Ensure that small notification window can be hidden by other windows.
    /// </summary>
    /// <param name="window"></param>
    public static void ShiftWindowIntoBackground(Window window)
    {
        try
        {
            // Prevent the window from grabbing focus away from other windows the first time is created.
            window.ShowActivated = false;

            // Do not use .Show() and .Hide() - not compatible with Citrix!
            if (window.Visibility != Visibility.Collapsed)
            {
                window.Visibility = Visibility.Collapsed;
            }

            // We can't allow the window to be maximized, as there is no de-maximize button!
            if (window.WindowState == WindowState.Maximized)
            {
                window.WindowState = WindowState.Normal;
            }

            window.Topmost = false;
        }
        catch (Exception)
        {
            // Gulp. Avoids "Cannot set visibility while window is closing".
        }
    }
}

Usage

Pour l'utiliser, vous devez créer la fenêtre dans votre ViewModel:

private ToastView _toastViewWindow;
private void ShowWindow()
{
    if (_toastViewWindow == null)
    {
        _toastViewWindow = new ToastView();
        _dialogService.Show<ToastView>(this, this, _toastViewWindow, true);
    }
    ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(_toastViewWindow);
    HideAndShowWindowHelper.ShiftWindowIntoForeground(_toastViewWindow);
}

private void HideWindow()
{
    if (_toastViewWindow != null)
    {
        HideAndShowWindowHelper.ShiftWindowIntoBackground(_toastViewWindow);
    }
}

Liens supplémentaires

Pour obtenir des conseils sur la façon de garantir qu'une fenêtre de notification revient toujours sur l'écran visible, consultez ma réponse: dans WPF, comment déplacer une fenêtre sur l'écran si elle est hors de l'écran? .

Contango
la source
5
"Code au niveau de l'entreprise" et quelques lignes plus tard catch (Exception) { }. Ouais bien ... Et il utilise du code qui n'est même pas affiché dans la réponse comme _dialogServiceou ShiftWindowOntoScreenHelper. De plus, demander à créer la fenêtre dans le côté du modèle de vue (ce qui brise fondamentalement tout le modèle MVVM) ...
Kryptos
@Kryptos Il s'agit d'un code de niveau entreprise. Je l'ai tapé de mémoire, et cette technique exacte est utilisée dans une grande entreprise FTSE100. La vraie vie est un peu moins vierge par rapport aux modèles de conception parfaits que nous visons tous.
Contango
Je n'aime pas le fait que nous conservions moi-même une instance de la fenêtre dans le modèle de vue, comme Kryptos l'a mentionné qui brise tout le point de mvvm, peut-être aurait-il pu être fait en codebehind à la place?
Igor Meszaros
1
@Igor Meszaros est d'accord. Maintenant que j'ai plus d'expérience, si je devais le refaire, j'ajouterais un comportement et le contrôlerais en utilisant un Func<>qui est lié au ViewModel.
Contango
7

J'ai rencontré un problème similaire avec une application WPF qui est invoquée à partir d'une application Access via l'objet Shell.

Ma solution est ci-dessous - fonctionne sous XP et Win7 x64 avec une application compilée sur la cible x86.

Je préfère de loin le faire que de simuler un alt-tab.

void Window_Loaded(object sender, RoutedEventArgs e)
{
    // make sure the window is normal or maximised
    // this was the core of the problem for me;
    // even though the default was "Normal", starting it via shell minimised it
    this.WindowState = WindowState.Normal;

    // only required for some scenarios
    this.Activate();
}
Seth
la source
4

Eh bien, puisque c'est un sujet brûlant ... voici ce qui fonctionne pour moi. J'ai des erreurs si je ne l'ai pas fait de cette façon car Activate () vous enverra une erreur si vous ne pouvez pas voir la fenêtre.

Xaml:

<Window .... 
        Topmost="True" 
        .... 
        ContentRendered="mainWindow_ContentRendered"> .... </Window>

Codebehind:

private void mainWindow_ContentRendered(object sender, EventArgs e)
{
    this.Topmost = false;
    this.Activate();
    _UsernameTextBox.Focus();
}

C'était la seule façon pour moi d'afficher la fenêtre en haut. Ensuite, activez-le pour pouvoir taper dans la case sans avoir à régler le focus avec la souris. control.Focus () ne fonctionnera pas à moins que la fenêtre ne soit active ();

Omzig
la source
2

Eh bien, j'ai trouvé une solution. Je fais l'appel à partir d'un crochet clavier utilisé pour implémenter un raccourci clavier. L'appel fonctionne comme prévu si je le mets dans un BackgroundWorker avec une pause. C'est un coup de coude, mais je n'ai aucune idée pourquoi cela ne fonctionnait pas à l'origine.

void hotkey_execute()
{
    IntPtr handle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
    BackgroundWorker bg = new BackgroundWorker();
    bg.DoWork += new DoWorkEventHandler(delegate
        {
            Thread.Sleep(10);
            SwitchToThisWindow(handle, true);
        });
    bg.RunWorkerAsync();
}
Facteur mystique
la source
Juste intéressé: avez-vous essayé Window.Activate (comme suggéré par Morten) et les autres suggestions? Ils semblent moins hacky que ce kludge admis.
Simon D.
Cela fait un bon bout de temps, mais oui, au moment où j'ai essayé ça
Factor Mystic
Cela ne fonctionne pas sur mon Windows XP. Je recommande la réponse de @Matthew Xavier.
Lex Li
2

Pour afficher TOUTE fenêtre actuellement ouverte, importez ces DLL:

public partial class Form1 : Form
{
    [DllImportAttribute("User32.dll")]
    private static extern int FindWindow(String ClassName, String WindowName);
    [DllImportAttribute("User32.dll")]
    private static extern int SetForegroundWindow(int hWnd);

et dans le programme Nous recherchons une application avec un titre spécifié (écrire le titre sans la première lettre (index> 0))

  foreach (Process proc in Process.GetProcesses())
                {
                    tx = proc.MainWindowTitle.ToString();
                    if (tx.IndexOf("Title of Your app WITHOUT FIRST LETTER") > 0)
                    {
                        tx = proc.MainWindowTitle;
                        hWnd = proc.Handle.ToInt32(); break;
                    }
                }
                hWnd = FindWindow(null, tx);
                if (hWnd > 0)
                {
                    SetForegroundWindow(hWnd);
                }
rahmud
la source
"Titre de votre application SANS PREMIÈRE LETTRE" Oof, hacky hacky hacky. Pourquoi ne pas l'utiliser IndexOfcorrectement à la place?
Courses de légèreté en orbite le
1

Le problème pourrait être que le thread appelant votre code à partir du hook n'a pas été initialisé par le runtime, donc les méthodes d'exécution ne fonctionnent pas.

Vous pouvez peut-être essayer de faire un appel pour rassembler votre code sur le thread d'interface utilisateur pour appeler votre code qui amène la fenêtre au premier plan.

joshperry
la source
1

Ces codes fonctionneront bien à tout moment.

Définissez d'abord le gestionnaire d'événements activé dans XAML:

Activated="Window_Activated"

Ajoutez la ligne ci-dessous à votre bloc constructeur de la fenêtre principale:

public MainWindow()
{
    InitializeComponent();
    this.LocationChanged += (sender, e) => this.Window_Activated(sender, e);
}

Et à l'intérieur du gestionnaire d'événements activé, copiez ces codes:

private void Window_Activated(object sender, EventArgs e)
{
    if (Application.Current.Windows.Count > 1)
    {
        foreach (Window win in Application.Current.Windows)
            try
            {
                if (!win.Equals(this))
                {
                    if (!win.IsVisible)
                    {
                        win.ShowDialog();
                    }

                    if (win.WindowState == WindowState.Minimized)
                    {
                        win.WindowState = WindowState.Normal;
                    }

                    win.Activate();
                    win.Topmost = true;
                    win.Topmost = false;
                    win.Focus();
                }
            }
            catch { }
    }
    else
        this.Focus();
}

Ces étapes fonctionneront bien et amèneront toutes les autres fenêtres dans la fenêtre de leurs parents.

Matrice
la source
0

Si vous essayez de masquer la fenêtre, par exemple, vous réduisez la fenêtre, j'ai constaté qu'en utilisant

    this.Hide();

le masquera correctement, puis en utilisant simplement

    this.Show();

affichera alors à nouveau la fenêtre comme l'élément le plus haut.

Chris
la source
0

Je voulais juste ajouter une autre solution à cette question. Cette implémentation fonctionne pour mon scénario, où CaliBurn est responsable de l'affichage de la fenêtre principale.

protected override void OnStartup(object sender, StartupEventArgs e)
{
    DisplayRootViewFor<IMainWindowViewModel>();

    Application.MainWindow.Topmost = true;
    Application.MainWindow.Activate();
    Application.MainWindow.Activated += OnMainWindowActivated;
}

private static void OnMainWindowActivated(object sender, EventArgs e)
{
    var window = sender as Window;
    if (window != null)
    {
        window.Activated -= OnMainWindowActivated;
        window.Topmost = false;
        window.Focus();
    }
}
d.moncada
la source
0

N'oubliez pas de ne pas placer le code qui montre cette fenêtre dans un gestionnaire PreviewMouseDoubleClick car la fenêtre active reviendra à la fenêtre qui a géré l'événement. Placez-le simplement dans le gestionnaire d'événements MouseDoubleClick ou arrêtez la propagation en définissant e.Handled sur True.

Dans mon cas, je manipulais le PreviewMouseDoubleClick sur une vue de liste et ne définissais pas le e.Handled = true, puis il a déclenché l'événement MouseDoubleClick avec le focus sur la fenêtre d'origine.

Michel P.
la source
-1

J'ai construit une méthode d'extension pour faciliter la réutilisation.

using System.Windows.Forms;
    namespace YourNamespace{
        public static class WindowsFormExtensions {
            public static void PutOnTop(this Form form) {
                form.Show();
                form.Activate();
            }// END PutOnTop()       
        }// END class
    }// END namespace

Appelez le constructeur de formulaire

namespace YourNamespace{
       public partial class FormName : Form {
       public FormName(){
            this.PutOnTop();
            InitalizeComponents();
        }// END Constructor
    } // END Form            
}// END namespace
Mike
la source
Salut Mike. Vous répondez à cette question assez tard. Pouvez-vous expliquer dans votre réponse pourquoi cette approche est différente (et peut-être meilleure) des très bonnes réponses qui ont déjà été publiées pour cette question?
Noel Widmer
Ce n'est que tardivement que j'avais juste besoin de le faire, et je suis tombé sur cela et je voulais partager comment j'ai résolu le problème, car d'autres voulaient l'utiliser.
Mike
Bien sûr, j'ai été choisi pour évaluer votre message et je voulais vous en informer. Il est toujours bon de fournir une nouvelle réponse si vous pensez que c'est une bonne contribution à la communauté.
Noel Widmer
2
Cette question concernait spécifiquement WPF, mais votre solution est pour WinForms.
Brian Reichle