Émulant fonctionnalité ShowDialog
-
11-09-2019 - |
Question
Je suis en train d'écrire une application (c # + WPF) où toutes les boîtes de dialogue de style modal sont mises en œuvre en tant que UserControl
sur le dessus d'une grille translucide couvrant la Window
principale. Cela signifie qu'il n'y a qu'un seul Window
et maintient l'apparence de toutes les applications entreprises.
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 est 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 la boîte de dialogue qu'elle a été soulevée événement fermé, mais je ne peux pas voir comment il est possible d'attendre cela sans accrocher le fil de l'interface graphique et empêchant ainsi l'utilisateur jamais en cliquant sur OK. Je sais que je peux prendre une fonction de délégué en tant que paramètre à la fonction ShowMessageBox
qui empêche l'inversion de type d'exécution, mais provoque toujours une syntaxe folle / indenter.
Suis-je manque quelque chose d'évident ou est-il un moyen standard de faire cela?
La solution
Vous pouvez jeter un oeil à cet article sur CodeProject et < a href = "http://msdn.microsoft.com/en-us/library/aa969773.aspx#Creating_a_Modal_Custom_Dialog_Box" rel = "noreferrer"> cet article sur MSDN. Le premier article vous guide à travers la création manuelle d'un dialogue modal de blocage, et le second article illustre comment créer des dialogues personnalisés.
Autres conseils
La façon de le faire est d'utiliser un DispatcherFrame objet .
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);
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
Vous pouvez ensuite écrire une fonction wrapper qui prend le recenseur et appelle MoveNext
(qui exécutera toutes les fonctions jusqu'à la prochaine yield return
) dans les gestionnaires de DialogClosed
.
Notez que la fonction d'emballage ne serait pas un appel de blocage.
Mettre en place 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 ..