Эмуляция функциональности ShowDialog - PullRequest
5 голосов
/ 01 декабря 2009

Я пишу приложение (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 и, таким образом, пользователь когда-либо нажимал ОК. Я знаю, что могу взять функцию делегата в качестве параметра функции ShowMessageBox, которая предотвращает инверсию выполнения, но все же вызывает некоторый сумасшедший синтаксис / отступ.

Я что-то упускаю из виду или есть стандартный способ сделать это?

Ответы [ 4 ]

5 голосов
/ 30 марта 2015

Способ сделать это - использовать объект 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);
5 голосов
/ 01 декабря 2009

Возможно, вы захотите взглянуть на эту статью о CodeProject и эту статью о MSDN. В первой статье рассказывается, как вручную создать модальное диалоговое окно блокировки, а во второй статье показано, как создавать настраиваемые диалоговые окна.

0 голосов
/ 01 декабря 2009

Установить еще один цикл сообщений в классе окна сообщений. Что-то вроде:

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

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

   return dialogResult;
}

Если вы посмотрите на Windows.Form в Reflector, вы увидите, что он делает что-то вроде этого

0 голосов
/ 01 декабря 2009

Вы можете превратить вашу функцию в итератор, который возвращает IEnumerator<CustomMessageBox>, а затем написать его так:

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

Затем вы должны написать функцию-обертку, которая принимает перечислитель и вызывает MoveNext (которая будет выполнять всю функцию до следующей yield return) в обработчиках DialogClosed.

Обратите внимание, что функция-обертка не будет блокирующим вызовом.

...