Общее диалоговое окно для WPF и Prism

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

Теперь я хочу повторить операцию с одним окном оболочки и надеюсь, что будет только одно диалоговое окно, тогда мои окна и виртуальные машины будут иметь гораздо меньшую связь, и я могу заимствовать шаблоны управления виртуальной машиной оболочки в управление диалогом.

Я вижу довольно много рекомендаций по непосредственному управлению всплывающими окнами и менее обобщенными немодальными окнами, но есть ли какой-либо установленный шаблон или руководство для использования только одного диалога для размещения различных виртуальных машин? Более того, доступна ли такая функция в Prism?

Я действительно хочу придерживаться принципа DRY, а наследование как в представлениях, так и в виртуальных машинах добавляет сложности, которые я не могу себе позволить в предположительно быстрой первой итерации прототипа.


person ProfK    schedule 04.01.2017    source источник


Ответы (2)


На самом деле это довольно просто, но имеет некоторые сложности. Во-первых, вам нужно создать настраиваемую диалоговую службу. Эта услуга может быть настолько простой или сложной, насколько вам нравится. Главное, что будет делать этот сервис, - это показывать диалог, который рассматривается как его собственная оболочка. Это означает, что диалоговое окно будет таким же, но его содержимое будет отличаться в зависимости от информации, которую вы передаете ему при его вызове. Итак, это означает настраиваемый диалог с собственными регионами. Чтобы справиться с использованием различных представлений в диалоговой оболочке, я бы использовал службу навигации.

Ваш диалог может выглядеть примерно так:

public interface IDialogService
{
    void ShowDialog(string uri);
}

public class DialogService : IDialogService
{
    private readonly IUnityContainer _container;
    private readonly IRegionManager _regionManager;

    public DialogService(IUnityContainer container, IRegionManager regionManager)
    {
        _container = container;
        _regionManager = regionManager;
    }

    public void ShowDialog(string uri)
    {
        var dialog = _container.Resolve<DialogShell>();
        //use a scoped region just in case you can have multiple instances
        var scopedRegion = _regionManager.CreateRegionManager();
        //set the region manager of the dialog to the scoped region
        RegionManager.SetRegionManager(dialog, scopedRegion);
        //navigate to show the desired view in the dialog
        scopedRegion.RequestNavigate(KnownRegionNames.ContentRegion, uri);
        //show the dialog
        dialog.Show();
    }
}

Вы можете изменить этот подход, чтобы он точно соответствовал вашим потребностям, но вы поняли идею.

РЕДАКТИРОВАТЬ: Я также хочу упомянуть, что вы можете даже сходить с ума от этого, разрешив своему диалогу иметь собственную отдельную навигацию внутри него и уникальную для каждого показанного экземпляра. У меня есть курс Pluralsight, который показывает, как это сделать, если вам интересно. https://www.pluralsight.com/courses/prism-showing-multiple-shells

person Community    schedule 11.01.2017
comment
Это выглядит пригодным для использования с некоторой адаптацией. Я не использую навигацию, только простые команды меню и кнопок, но в данном случае это просто светская беседа. Подробнее позже. Спасибо. - person ProfK; 12.01.2017
comment
Поскольку это работоспособное решение вашей проблемы, как насчет того, чтобы отметить его как ответ? - person ; 17.01.2017

Что ж, я не знаю ни одного готового решения, но создать такую ​​реализацию многоразового диалогового окна не так уж и сложно. Собственно, что-то подобное я реализовал несколько лет назад. Ну, это было на другой работе, поэтому у меня больше нет доступа к коду. Кроме того, я не могу вспомнить все детали, но я могу попытаться дать вам основное представление о такой реализации.

Вы можете создать DialogVm, который предоставляет общие функциональные возможности диалога.

Прежде всего, что нужно для диалога на уровне презентации? Обычно три кнопки, вроде ...

  • Применить, Отмена и Закрыть (диалоговое окно "Изменение")
  • ОК и Отмена или Да и Нет (диалоговое окно с вопросом)
  • Хорошо (в случае окна сообщения)

Как видите, вам нужны три команды (ICommand документ). Фактически, я создал DelegateCommand реализацию (на основе this). ICommand.CanExecute определяет, активирована или отключена привязанная кнопка. Если команда пуста, кнопка должна быть скрыта.

(Если вы используете правильный элемент управления макетом, положения кнопок настраиваются правильно, если кнопка не отображается.)

Чтобы обеспечить поддержку более чем четырех сценариев, описанных выше, я добавил свойство CommandTitle в DelegateCommand, чтобы содержимое кнопки поступало оттуда.

Далее вам понадобится свойство Title для заголовка диалога. Так что добавьте это в DialogVm.

Если вы хотите закрыть диалоговое окно (только необходимо, если это дочерний элемент Window), выполнив команду, вы можете выполнить этот подход. Конечно, я использовал ту версию, о которой писал там. Но другие тоже выглядят многообещающими.

Последняя открытая точка - это свойство, которое представляет различное содержимое диалогового окна. Если я правильно помню, я использовал небольшой набор моделей представления и соответствующий DataTemplates (и, конечно, TemplateSelector, который предоставляет правильный шаблон на основе типа виртуальной машины). Конечно, вам также понадобится ContentPresenter элемент управления в вашем диалоге, который показывает DataTemplate, предоставленный TemplateSelector.

Это единственный недостаток, это только хороший подход, если у вас есть только несколько разных типов диалогов (например, окно вопроса, окно сообщения ...)

Использовать довольно просто. Просто инициализируйте экземпляр DialogVm с желаемой логикой ICommand, DialogContentVm (как бы вы его ни называли), передайте его в DialogWindow (возможно, вы хотите использовать sth (например, всплывающее меню) и представить его пользователю.

Надеюсь, это поможет. Если вам нужна дополнительная информация или помощь, пожалуйста, дайте мне знать.

person DHN    schedule 04.01.2017
comment
Спасибо. То, что вы предлагаете, довольно близко к тому, что я имел в виду, за исключением DataTemplate использования. Веб-разработка была моим основным направлением за много лет до недавних двух-трех лет работы с WPF, поэтому я просто использую простой UserControl в качестве представления, которое привязано к ContentControl в окне. Затем вместо выбора шаблонов я стремлюсь использовать автоматическое соединение vm Prism, поэтому моя команда ShowView просто использует Untiy для разрешения экземпляра представления, а vm уже привязан. - person ProfK; 04.01.2017
comment
@ProfK: А, похоже, это лучший вариант, чем подход DataTemplate. Спасибо за подсказку. :) - person DHN; 04.01.2017
comment
Пожалуйста, не обижайтесь на награду. Я не сомневаюсь, что ваш совет заслуживает доверия, но он основан на чистом WPF, а не на Prism, и я хотел получить еще несколько ответов от властей по этой структуре. К сожалению, формулировка этой кнопки выбора SO. - person ProfK; 10.01.2017
comment
@ProfK: Не волнуйся. Я не обиделась. Вам решать, достаточно ли для вас моего ответа. ; o) Поскольку я не знал об автопроводе Prism VM ... это прекрасно и понятно. Хотя я считаю, что вам нужно лишь немного изменить мой подход. ; o) Так что расслабьтесь, я надеюсь, что SB предоставит вам нужную информацию. - person DHN; 11.01.2017