2010-01-09 7 views
6

Comment puis-je forcer ShowDialog à revenir d'un thread d'arrière-plan?WPF - Force ShowDialog à retourner

J'ai une application WPF construite au-dessus d'une structure C++/CLR qui écoute les messages envoyés par le framework. Un message particulier est si important que j'ai besoin de fermer toutes les fenêtres actuelles. Toutefois, si un modal Dialog (créé par ShowDialog à partir de ma fenêtre principale) est actif et en attente de l'entrée de l'utilisateur, la fenêtre ne se ferme pas car il attend ShowDialog pour retourner. Comment puis-je forcer le modal Dialog pour fermer et dérouler l'exécution de code?

J'ai essayé de régler le DialogResult ou d'appeler Close mais cela ne semble pas fonctionner.

Edit: Le Dialog est créé par ma fenêtre principale qui attend une valeur de retour, comme ceci: (dans un gestionnaire d'événements clic dans MainWindow):

Window modalDialog = new Window(); 
bool ret = (bool)modalDialog.ShowDialog(); 
if (ret == true) 
{ 
// do stuff 
} 
else 
{ 
// do some other stuff 
} 

Lorsque le cadre envoie un message (à venir en sur un fil différent de celui de l'interface utilisateur), j'appelle le MainWindow.Close(). Le dialogue modal se ferme à ce stade, cependant le code vérifiant la valeur de retour du Dialog (après ShowDialog) est toujours dans la pile. D'une certaine manière, cela force la fenêtre principale à ne pas disparaître.

Répondre

3

Lorsque la boîte de dialogue reçoit le message WM_CLOSE il définit un indicateur qui provoque ShowDialog pour revenir après la WM_CLOSE et les messages contenant ont été entièrement traitées. Donc, si vous faites un Dispatcher.Invoke() sur votre fil pour appeler MainWindow.Close(), le ShowDialog() ne reviendra pas avant que le Dispatcher.Invoke() ne soit terminé.

Donc la solution simple est de revenir du Dispatcher.Invoke() pour obtenir le ShowDialog() pour revenir. Si plus de traitement est requis, faites immédiatement un autre Dispatcher.Invoke().

Si vous faites la transition fil d'une autre manière que Dispatcher.Invoke(), ou si le ShowDialog() ne revient pas après le retour d'appel Dispatcher.Invoke(), vous pouvez avoir à poster une partie du code entourant votre appel afin que nous Window.Close() peut voir ce que vous faites réellement.

1

Vous ne pouvez pas forcer ShowDialog à retourner mais vous pouvez faire en sorte que la fenêtre écoute un événement envoyé par votre infrastructure qui peut lui dire de se fermer. Dans l'exemple ci-dessous, l'événement Progress a un indicateur "Terminé" qui ferme la fenêtre une fois terminé.

SomeGenerator IG = Manager.SomeGenerator(); 
SomeWindow PP = new SomeWindow(); 
IG.ProgressEvent += PP.ProgressEvent; 
IG.ExecuteAsync();    
PP.ShowDialog(); 
+0

J'ai édité ma question originale pour indiquer que ShowDialog devrait renvoyer une valeur et que la fenêtre parente est censée faire un traitement avec la valeur ... – Hypherion

0

Je réalise maintenant que je ne peux pas forcer ShowDialog à retourner et continuer l'exécution quand je le veux. Le gestionnaire d'événements pour la demande que je reçois du framework doit sortir de son contexte pour que la pile d'appels puisse être déroulée et que la boîte de dialogue modale puisse traiter le message Close.

J'ai fini par définir un indicateur booléen, demandant aux modaux de se fermer, puis de retourner depuis mon gestionnaire d'événement de framework. C'est seulement à ce moment-là que ShowDialog reviendra et que je pourrai vérifier le drapeau que j'ai défini et continuer l'action demandée.

+0

Il semble que ma réponse était la bonne et m'a aidé à résoudre votre problème . Si vous êtes d'accord, vous devriez le marquer "correct" pour les futurs visiteurs. –

Questions connexes