приостановить процесс viewmodel для пользовательского ввода - PullRequest
1 голос
/ 19 января 2011

Я просматривал примеры типичной проблемы «Поднять диалог из viewmodel», отмечая 3 основных решения:

  • использовать прикрепленное поведение
  • использовать шаблон-посредник
  • пользуйтесь услугой

Я немного застрял и пытаюсь найти решение, которое легко вписывается в мое проблемное пространство - это очень простая проблема копирования файлов:

  • Моя модель представления обрабатывает цикл (копирует список файлов)
  • Когда файл уже существует в месте назначения, мне нужно вызвать модальное диалоговое окно, чтобы получить подтверждение для замены
  • VM должен дождаться и получить подтверждение, прежде чем продолжить
  • «Модальное диалоговое окно» на самом деле не новое окно, а скрытое наложение в моем MainWindow, согласно http://www.codeproject.com/KB/WPF/wpfmodaldialog.aspx (спасибо, Рональд!)

Я в основном там, но у меня самая большая борьба: Как приостановить цикл в viewmodel, пока он ждет ввода - как получить вход обратно в модель представления внутри цикла, чтобы он мог продолжить

Пока что я склоняюсь к сервисному решению, потому что кажется, что это прямой вызов метода с возвратом, которого vm должен ждать. Однако это означает, что сервис должен быть привязан непосредственно к представлению, чтобы сделать элемент видимым?

Если кто-то может опубликовать какой-то простой код, который имеет непосредственное отношение к этой проблеме, я (и сеть) был бы очень рад! Спасибо!

1 Ответ

0 голосов
/ 19 января 2011

Например, у вас есть сервис под названием 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);
}

Но использовать его будет не так удобно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...