2009-12-01 4 views
5

J'écris une application (C# + wpf) dans laquelle toutes les boîtes de dialogue de style modal sont implémentées sous forme de UserControl au-dessus d'une grille translucide couvrant le Window principal. Cela signifie qu'il n'y a qu'un seul Window et il maintient l'aspect et la convivialité de toutes les applications des entreprises.Emulation de la fonctionnalité ShowDialog

Pour afficher une MessageBox, la syntaxe est la suivante:

CustomMessageBox b = new CustomMessageBox("hello world"); 
c.DialogClosed +=()=> 
{ 
    // the rest of the function 
} 
// this raises an event listened for by the main window view model, 
// displaying the message box and greying out the rest of the program. 
base.ShowMessageBox(b); 

Comme vous pouvez le voir, non seulement le flux d'exécution en fait inversée, mais son horriblement bavard par rapport à la version .NET classique:

MessageBox.Show("hello world"); 
// the rest of the function 

ce que je cherche vraiment est un moyen de ne pas revenir de base.ShowMessageBox jusqu'à ce que le dialogue événement fermé a été soulevée par elle, mais je ne peux pas voir comment il est possible d'attendre cela sans accrocher le fil de l'interface graphique et donc nous empêcher de nous En cliquant sur OK. Je suis conscient que je peux prendre une fonction de délégué en tant que paramètre de la fonction ShowMessageBox qui empêche l'inversion de l'exécution, mais provoque quand même une syntaxe/indentation folle.

Ai-je manqué quelque chose d'évident ou existe-t-il un moyen standard de le faire?

Répondre

5

Vous pouvez jeter un oeil à this article sur CodeProject et this article sur MSDN. Le premier article vous guide dans la création manuelle d'une boîte de dialogue modale de blocage, et le deuxième article explique comment créer des boîtes de dialogue personnalisées.

+0

Le premier article lié montre un exemple parfait de la façon de procéder. – Guy

0

Vous pouvez faire votre fonction dans un itérateur qui retourne un IEnumerator<CustomMessageBox>, puis l'écrire comme ceci:

//some code 
yield return new CustomMessageBox("hello world"); 
//some more code 

alors vous écrire une fonction wrapper qui prend le recenseur et appelle MoveNext (qui exécutera tous la fonction jusqu'à la suivante yield return) dans les gestionnaires DialogClosed.

Notez que la fonction wrapper ne serait pas un appel bloquant.

0

Définissez une autre boucle de message dans la classe de boîte de message. Quelque chose comme:

public DialogResult ShowModal() 
{ 
    this.Show(); 

    while (!this.isDisposed) 
    { 
    Application.DoEvents(); 
    } 

    return dialogResult; 
} 

Si vous regardez Windows.Form dans le réflecteur, vous verrez qu'il fait quelque chose comme ça ..

+0

Il utilise WPF, pas WinForms. – SLaks

+0

Ah, j'ai raté ça. WPF est complètement différent? Est-ce que les fenêtres n'ont plus de boucles de messages? –

4

La façon de le faire est à l'aide d'un objet DispatcherFrame.

var frame = new DispatcherFrame(); 
CustomMessageBox b = new CustomMessageBox("hello world"); 
c.DialogClosed +=()=> 
{ 
    frame.Continue = false; // stops the frame 
} 
// this raises an event listened for by the main window view model, 
// displaying the message box and greying out the rest of the program. 
base.ShowMessageBox(b); 

// This will "block" execution of the current dispatcher frame 
// and run our frame until the dialog is closed. 
Dispatcher.PushFrame(frame);