funcionalidad ShowDialog emulando
-
11-09-2019 - |
Pregunta
Estoy escribiendo una aplicación (c # + WPF), donde todos los diálogos de estilo modal se implementan como un UserControl
encima de una rejilla transparente que cubre la Window
principal. Esto significa que sólo hay una Window
y mantiene la apariencia de todas las aplicaciones de las empresas.
Para mostrar una MessageBox
, la sintaxis es la siguiente:
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);
Como se puede ver, no sólo es el flujo de ejecución realidad invertida, pero su horrible detallado en comparación con la versión clásica .NET:
MessageBox.Show("hello world");
// the rest of the function
Lo que estoy realmente buscando es una manera de no volver a base.ShowMessageBox
hasta que el diálogo cerrado evento ha sido planteada por él, pero no puedo ver cómo es posible esperar a que este sin colgar el hilo GUI y por lo tanto evitando que el usuario alguna vez haciendo clic en OK. Soy consciente de que puedo tener una función delegada como parámetro a la función ShowMessageBox
qué tipo de evita la inversión de la ejecución, pero todavía causa alguna loca sintaxis / sangría.
Me estoy perdiendo algo obvio o hay una manera estándar de hacer esto?
Solución
Es posible que desee echar un vistazo a este artículo en CodeProject y < a href = "http://msdn.microsoft.com/en-us/library/aa969773.aspx#Creating_a_Modal_Custom_Dialog_Box" rel = "noreferrer"> este artículo en MSDN. El primer artículo le guía a través de la creación manual de un diálogo modal de bloqueo, y el segundo artículo muestra cómo crear cuadros de diálogo personalizados.
Otros consejos
La forma de hacer esto es mediante el uso de un DispatcherFrame objeto .
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);
Se podría hacer su función en un iterador que devuelve un IEnumerator<CustomMessageBox>
, a continuación, escribir así:
//some code
yield return new CustomMessageBox("hello world");
//some more code
A continuación, escribir una función de contenedor que lleva el empadronador y llama MoveNext
(que ejecutará todas las funciones hasta la próxima yield return
) en los manipuladores DialogClosed
.
Tenga en cuenta que la función de contenedor no sería una llamada de bloqueo.
Configurar otro mensaje de bucle en la clase de cuadro de mensaje. Algo así como:
public DialogResult ShowModal()
{
this.Show();
while (!this.isDisposed)
{
Application.DoEvents();
}
return dialogResult;
}
Si nos fijamos en Windows.Form en Reflector verá que hace algo como esto ..