C# 模拟ShowDialog功能

C# 模拟ShowDialog功能,c#,wpf,events,dialog,messagebox,C#,Wpf,Events,Dialog,Messagebox,我正在编写一个应用程序(c#+wpf),其中所有模式样式对话框都作为UserControl实现在覆盖主窗口的半透明网格上。这意味着只有一个窗口,它保持了所有应用程序的外观 要显示消息框,语法如下: CustomMessageBox b = new CustomMessageBox("hello world"); c.DialogClosed += ()=> { // the rest of the function } // this raises an event listened

我正在编写一个应用程序(c#+wpf),其中所有模式样式对话框都作为
UserControl
实现在覆盖主
窗口的半透明网格上。这意味着只有一个
窗口
,它保持了所有应用程序的外观

要显示
消息框
,语法如下:

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); 
正如您所看到的,不仅执行流程实际上是颠倒的,而且与经典的.NET版本相比,执行流程极其冗长:

MessageBox.Show("hello world");
// the rest of the function
我真正想要的是一种在对话框关闭事件被它引发之前不从
base.ShowMessageBox
返回的方法,但是我看不出在不挂起GUI线程的情况下,如何等待它,从而阻止用户点击OK。我知道我可以将委托函数作为
ShowMessageBox
函数的参数,这可以防止执行反转,但仍然会导致一些疯狂的语法/缩进


我是否遗漏了一些明显的东西,或者是否有一个标准的方法来做到这一点

您可以将函数变成一个迭代器,返回一个
IEnumerator
,然后这样编写:

//some code
yield return new CustomMessageBox("hello world");
//some more code
然后,您将在
对话框closed
处理程序中编写一个包装函数,该函数接受枚举数并调用
MoveNext
(它将执行所有函数,直到下一个
返回


请注意,包装器函数不会是一个阻塞调用。

您可能想看看关于CodeProject的文章和关于MSDN的文章。第一篇文章指导您手动创建阻塞模式对话框,第二篇文章说明如何创建自定义对话框。

在MessageBox类中设置另一个消息循环。比如:

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

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

   return dialogResult;
}

如果你在Reflector中查看Windows.Form,你会看到它做了类似的事情。

这样做的方法是使用一个对象


他用的是WPF,不是WinForms。啊,我错过了。WPF完全不同?windows不再有消息循环了吗?链接的第一篇文章展示了一个完美的例子。
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);