模拟ShowDialog功能

时间:2009-12-01 15:05:01

标签: c# wpf events dialog messagebox

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

要显示MessageBox,语法如下:

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函数的一个参数来阻止执行的反转,但仍会导致一些疯狂的语法/缩进。

我错过了一些明显的东西,还是有标准的方法来做到这一点?

4 个答案:

答案 0 :(得分:5)

您可能需要查看有关CodeProject的this文章和MSDN上的this文章。第一篇文章将指导您手动创建阻止模式对话框,第二篇文章说明如何创建自定义对话框。

答案 1 :(得分:5)

执行此操作的方法是使用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);

答案 2 :(得分:0)

你可以把你的函数变成一个返回IEnumerator<CustomMessageBox>的迭代器,然后像这样写:

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

然后,您将编写一个包装器函数,该函数接受枚举器并调用MoveNext(将在yield return处理程序中执行所有函数,直到下一个DialogClosed

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

答案 3 :(得分:0)

在消息框类中设置另一个消息循环。类似的东西:

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

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

   return dialogResult;
}

如果你看一下Reflector中的Windows.Form,你会发现它有类似的东西..