web-dev-qa-db-fra.com

La boîte de dialogue modale ne s'affiche pas au-dessus des autres fenêtres

J'utilise Window.ShowDialog() pour ouvrir une fenêtre modale dans mon application WPF (MVVM), mais cela me permet de naviguer vers d'autres fenêtres à l'aide de la barre des tâches Windows (Windows 7).

Considérez ceci: J'ai 3 fenêtres non modales ouvertes dans mon application. Maintenant, l'un d'eux ouvre une fenêtre modale utilisant Window.ShowDialog(). J'ai également défini Application.MainWindow en tant que propriétaire de la fenêtre modale. En effet, j'utilise la messagerie MVVM et le gestionnaire de messages pour ouvrir une nouvelle fenêtre est centralisé dans App.xaml.cs. La fenêtre s'ouvre de façon modale - aucun problème. Cependant, Windows 7 me permet de basculer vers les autres fenêtres d'application à partir de la barre des tâches. Cela conduit à une situation où la fenêtre modale passe derrière une autre fenêtre, que je préfère ne pas avoir.

Je ne peux rien faire sur les autres fenêtres tant que le modal est ouvert, mais ce serait bien si la fenêtre modale restait toujours en haut tant qu'elle était ouverte. Existe-t-il un moyen de désactiver la commutation de la barre des tâches lorsque le modal est ouvert? Pour info - toutes les fenêtres ouvertes lancées depuis l'application apparaissent comme des entrées distinctes dans la barre des tâches.

Merci d'avance!

24
Pratz

Il n'y a pas de code pour baser cela, mais il semble que vous ayez laissé certaines propriétés sur le Window que vous avez créé et attendu ShowDialog to appliquer une sémantique supplémentaire de "dialogue":

Window window = new Window()
{
    Title = "Modal Dialog",
    ShowInTaskbar = false,               // don't show the dialog on the taskbar
    Topmost = true,                      // ensure we're Always On Top
    ResizeMode = ResizeMode.NoResize,    // remove excess caption bar buttons
    Owner = Application.Current.MainWindow,
};

window.ShowDialog();
60
user7116

Définissez simplement la propriété propriétaire de la fenêtre sur la fenêtre d'appel. Ensuite, l'activation de l'application WPF dans la barre des tâches active non seulement la fenêtre principale, mais également la fenêtre enfant modale et l'amène au premier plan.

ChildWindow C = new ChildWindow();
C.Owner = this;
C.ShowDialog();
11
Bitbauer

La définition de Topmost sur True (Topmost = True) entraîne la boîte de dialogue en haut de toutes les fenêtres du système (pas seulement dans l'application).

Vous pouvez donc essayer d'enregistrer l'événement Activé dans votre fenêtre principale:

Activated += WindowActivated;

et activer une fenêtre propriétaire de la boîte de dialogue modale à chaque fois qu'une autre fenêtre principale de votre application devient active.

private void WindowActivated(object sender, EventArgs e)
{
    Window window = Application.Current.Windows.OfType<YourMainWindow>().FirstOrDefault(p => p != this && !p.IsActive && p.OwnedWindows.Count > 0);
    if (window != null)
    {
        window.Activate();
    }
}

Ce hack simple suppose que toutes vos fenêtres enfants sont modales, mais vous pouvez écrire une logique plus sophistiquée.

10
koalix

J'ai fini par utiliser une combinaison de quelques réponses ici. La réponse acceptée a été utile au début, mais comme d'autres personnes ici l'ont souligné, la configuration Topmost = true signifie que la fenêtre est toujours au-dessus de toute autre application en cours d'exécution. Ma solution était la suivante:

var myWindow = new MyWindowType();
myWindow.Owner = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);

J'ai d'abord utilisé:

myWindow.Owner = Application.Current.MainWindow;

Cependant, cette méthode pose des problèmes si vous avez trois fenêtres ouvertes comme ceci:

MainWindow
   |
   -----> ChildWindow1

               |
               ----->  ChildWindow2

Ensuite, définissez ChildWindow2.Owner = Application.Current.MainWindow définira le propriétaire de la fenêtre comme étant sa fenêtre de grand-parent, et non sa fenêtre parent.

Pour accélérer les choses, je l'ai ajouté comme extrait de code dans Visual Studio. Si vous ajoutez les éléments suivants à Outils -> Gestionnaire d'extraits de code -> Mes extraits de code:

<CodeSnippets
    xmlns="http://schemas.Microsoft.com/VisualStudio/2010/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>MVVM Set owner of page to be current active window</Title>
      <Shortcut>owner</Shortcut>
    </Header>
    <Snippet>
      <Code Language="CSharp">
        <![CDATA[System.Windows.Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

En tapant "propriétaire" et en appuyant deux fois sur la touche de tabulation, vous ajouterez "Application.CurrentWindows... 'participer automatiquement pour vous.

3
GrandMasterFlush

J'ai dû faire un peu de modification. J'ai dû définir le propriétaire et activer la fenêtre. Vérifiez la fenêtre contextuelle et activez la fenêtre comme indiqué ci-dessous.

        var enumerator = Application.Current.Windows.GetEnumerator();
        while (enumerator.MoveNext())
        {
            Window window = (Window)enumerator.Current;
            if (window != null && window.GetType() == typeof(PopUpWindow))
            {
                window.Activate();
            }
        }
1
DiAgo