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

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

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

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

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

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();
    }
}

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

EDIT: я также хочу упомянуть, что вы даже можете сойти с ума от этого, позволяя вашему диалогу иметь свою собственную отдельную навигацию внутри него и уникальную для каждого экземпляра, который показан. У меня есть курс Pluralsight, который показывает, как это сделать это если вам интересно. https://www.pluralsight.com/courses/prism-showing-multiple-shells


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

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

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

  • применить, отмена и закрыть (диалоговое окно модификации)
  • Ok и отмена или да и нет (диалог вопрос)
  • Ok (в случае окна сообщения)

так как вы можете видеть, Вам нужно три команды (ICommand doc). На самом деле, я создал DelegateCommand реализация (на основе этой). ICommand.CanExecute определяет, будет ли кнопка отключена или включена. Если команда имеет значение null, кнопка должна быть скрыта.

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

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

следующее, что вам понадобится Title свойство для заголовка диалогового окна. Поэтому добавьте это в DialogVm.

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

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

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

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

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