2017-01-04 2 views
7

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

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

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

Я хочу по-настоящему придерживаться принципа СУХОЙ, а наследование как в представлениях, так и в виртуальных машинах добавляет сложности, которые я не могу себе позволить на предполагаемом быстром прототипе первой итерации.

ответ

1

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

Ваш диалог может выглядеть следующим образом:

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

+0

Это выглядит удобно, с некоторой адаптацией.Я не использую навигацию, просто меню и кнопки, но это просто небольшая беседа в этом сценарии. Позднее. Спасибо. – ProfK

+0

Поскольку это приемлемое решение вашей проблемы, как насчет ее маркировки как ответа? –

4

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

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

Прежде всего, что необходимо для диалога в слое представления? Как правило, три кнопки, как ...

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

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

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

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

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

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

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

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

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

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

+0

Спасибо. То, что вы предлагаете, довольно близко к тому, что я имел в виду, за исключением использования DataTemplate. Веб-разработчик был моей основной линией за многие годы до последних двух-трех лет в WPF, поэтому я просто использую простой «UserControl» в качестве представления, связанного с «ContentControl» в окне. Затем вместо выбора шаблонов я пытаюсь использовать auto-wire Prism vm, поэтому моя команда ShowView' просто использует Untiy для разрешения экземпляра представления, а vm уже привязан. – ProfK

+0

@ProfK: Ах, это лучший вариант, чем метод DataTemplate. Спасибо за подсказку. :) – DHN

+0

Пожалуйста, не обижайтесь на щедрость. Я не сомневаюсь, что ваш совет заслуживает доверия, но это чистый WPF, а не основанный на Prism, и мне хотелось получить еще несколько ответов от «властей» в этой области. Несчастливо для SO-формулировки этой кнопки выбора. – ProfK