Библиотека WPF / Prism и несколько оболочек - PullRequest
2 голосов
/ 10 мая 2011

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

  • 1-й вопрос: как RegionManager вступит в игру для классов, специфичных для модуля (докладчиков), которые должны взаимодействовать с основным элементом управления картой? Обычно в RegionManager вы регистрируете конкретное представление, которое связано с ViewModel, но в моем случае есть одно представление (представление карты) с несколькими выступающими на нем выступающими.

  • 2-й вопрос: мне нужно иметь возможность открывать несколько окон (оболочек) - немного похоже на документ MS Word - которые должны быть расширены модулями плагинов. В среде с одной оболочкой, когда создаются экземпляры отдельных классов модулей, они могут использовать контейнер внедрения зависимостей, чтобы получить ссылку на RegionManager или саму оболочку, чтобы получить доступ к элементу управления картой. Однако с несколькими оболочками я не вижу, как получить доступ к элементу управления карты нужной оболочки. Контейнер зависимостей имеет ссылки на объект, глобальный для приложения, не специфичный для оболочки, в которой я сейчас работаю. То же самое верно для EventAggregator.

Любой ввод будет очень приветствоваться,

Эд

Ответы [ 2 ]

2 голосов
/ 11 мая 2011

После нескольких часов чтения статей и форумов, связанных с Prism, я наткнулся на статью «Как создать приложение в стиле Outlook» в блоге Эрвина ван дер Валька - Как создать приложение в стиле Outlook .

В одной части архитектуры для разрешения экземпляров типов использовался дочерний контейнер Unity. Это именно то, что мне было нужно для ответа на мой 2-й вопрос: мне нужно было сделать инъекцию зависимостей "scoped" (по окнам) (например, EventAggregator, управление областью окна и т. Д.)

Вот как я создаю новое окно:

private IShellWindow CreateNewShell(IRegionManager regionManager)
{
  IUnityContainer childContainer = this.Container.CreateChildContainer();

  ... register types in child container ...      

  var window = new ShellWindow();
  RegionManager.SetRegionManager(window, regionManager);
  window.Content = childContainer.Resolve<MapDocumentView>();
  return window;
}

Таким образом, MapDocumentView и все его компоненты будут внедрены (при необходимости) в экземпляры области окна.

Теперь, когда у меня есть возможности для ввода объектов с областью видимости, я могу получить карту с областью окна в моем модуле MapPresenter. Чтобы ответить на мой первый вопрос, я определил интерфейс IHostApplication, который реализуется Bootstrapper, у которого есть свойство MapPresenterRegistry. Этот интерфейс добавлен в основной контейнер.
После инициализации модули зарегистрируют своих презентаторов, а при создании окна они будут созданы.

Итак, для инициализации модуля:

public void Initialize() 
{
  ...
  this.hostApplication.MapPresenterRegistry.Add(typeof(ModuleSpecificMapPresenter));
  ...
}

Код, который инициализирует окно карты:

private void View_Loaded(object sender, RoutedEventArgs e)
{
  // Register map in the == scoped container ==
  container.RegisterInstance<IMap>(this.View.Map);

  // Create map presenters
  var hostApplication = this.container.Resolve<IHostApplication>();
  foreach (var mapPresenterType in hostApplication.MapPresenterRegistry)
  {
    var mapPresenter = this.container.Resolve(mapPresenterType) as IMapPresenter;
    if (mapPresenter != null)
    {
      this.mapPresenters.Add(mapPresenter);
    }
  }
}

MapPresenter для конкретного модуля:

public ModuleSpecificMapPresenter(IEventAggregator eventAggregator, IMap map)
{
  this.eventAggregator = eventAggregator;
  this.map = map;
  this.eventAggregator.GetEvent<AWindowSpecificEvent>().Subscribe(this.WindowSpecificEventFired);

  // Do stuff on with the map
}

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

Если у вас есть какие-либо дальнейшие мысли, я был бы рад выслушать их. Эдуард

1 голос
/ 11 мая 2011

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

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

public interface IPin
{
    Point Coordinates { get; }
    IPinView View { get; }
    //You can use a view model or a data template instead of the view interface, but this example is the simplest
}

public interface IPinsCollectionState
{
    ObservableCollection<IPin> Pins { get; }
}

Ваша модель основного вида и различные модули могут получить этот интерфейс в качестве параметра конструктора:

public class MapViewModel
{
    public MapViewModel(IPinsCollectionState collectionState)
    {
        foreach (var item in collectionState.Pins)
        { /* Do something */ };

        collectionState.Pins.CollectionChanged += (s, e) => {/* Handle added or removed items in the future */};
    }

    //...
}

Пример модели представления модуля:

public class Module1ViewModel
{
    public Module1ViewModel(IPinsCollectionState collectionState)
    {
        //somewhere in the code
        collectionState.Pins.Add(new Module1Pin());
    }
}

Второй вопрос можно решить разными способами:

  • Application.Current.Windows
  • Глобальная MainViewModel, которая содержит список ShellViewModel, и если вы добавите новую модель представления, она будет отображаться в новом окне. Загрузчик является единственным для всех окон.
  • Некоторое общее состояние, которое передается конструктору загрузчика.

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

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