Например, у вас есть сервис под названием IDialogService
со следующим интерфейсом:
public interface IDialogService
{
bool ConfirmAction(string title, string confirmationText);
}
Как вы упомянули, для того, чтобы служба могла показывать фактическое диалоговое окно, она должна иметь ссылку на представление, которое будет отображать фактический оверлейный элемент. Но вместо прямой ссылки на представление я предпочитаю ссылаться на него через интерфейс. Давайте назовем это ICanShowDialog
, и в нем будут следующие члены:
public interface ICanShowDialog
{
void ShowDialog(object dialogContent);
void HideDialog();
}
Этот интерфейс будет реализован вашим представлением, которому принадлежит оверлей диалога (например, ваше главное окно).
Теперь интересная часть: приостановка выполнения кода во время отображения диалога. Прежде всего, я бы порекомендовал вам не использовать оверлейные элементы, а по возможности использовать обычные окна. Тогда у вас не будет этой проблемы. Вы можете стилизовать диалоговое окно так, чтобы оно выглядело как элемент наложения.
В любом случае, если вы все еще хотите использовать оверлейные элементы, вы можете сделать следующий трюк, чтобы приостановить выполнение кода:
Вот псевдокод ConfirmAction
метода IDialogService
:
public bool ConfirmAction(string title, string confirmationText)
{
ConfirmationDialogView dialogView = new ConfirmationDialogView(title, confirmationText);
DialogShower.ShowDialog(dialogView); // DialogShower is of type ICanShowDialog
while (!dialogView.ResultAvailable)
{
DispatcherUtils.DoEvents();
}
DialogShower.HideDialog();
return dialogView.Result;
}
Вот код DispatcherUtils.DoEvents()
(который был взят отсюда: http://dedjo.blogspot.com/2007/08/how-to-doevents-in-wpf.html):
public static class DispatcherUtils
{
public static void DoEvents()
{
DispatcherFrame f = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(
DispatcherPriority.Background,
(SendOrPostCallback)delegate(object arg) {
DispatcherFrame fr = arg as DispatcherFrame;
fr.Continue=True;
}, f);
Dispatcher.PushFrame(frame);
}
}
Но я должен предупредить вас. Использование DoEvents
может привести к некоторым незначительным ошибкам, вызванным внутренними циклами диспетчера.
В качестве альтернативы приостановке выполнения кода во время отображения диалога вы можете использовать обратные вызовы:
public interface IDialogService
{
void ConfirmAction(string title, string confirmationText, Action<bool> dialogResultCallback);
}
Но использовать его будет не так удобно.