Prism / MEF: как зарегистрировать ViewWithRegion без жесткого кодирования имени региона - PullRequest
6 голосов
/ 14 сентября 2011

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

Например, скажем, у нас есть модуль, который будет использоваться в двух разных приложениях. В одном приложении его разработчик может назвать регион модуля «DetailsRegion», а в другом его разработчик может назвать его «ResultsRegion».

Каждый пример, который я могу найти, регистрирует представление с помощью региона путем жесткого кодирования имени региона в определении класса модуля :

myRegionManager.RegisterViewWithRegion("RegionNameHere", GetType(ModuleViewType))

Что я хочу сделать, это поместить имя региона в файл app.config основного приложения и передать это имя модулю. Примерно так:

В файле app.config основного приложения Shell:

<Modules>
   <SearchModule>
       <add key="RegionName" value="SearchRegion" />
    </SearchModule>
</Modules>

А в файле класса модуля:

Dim settings As NameValueCollection = CType(ConfigurationManager.GetSection("Modules/SearchModule"), NameValueCollection)
Dim regionName as string = settings("RegionName")
myRegionManager.RegisterViewWithRegion(regionName, GetType(SearchModuleType)

В некотором смысле, это будет последний шаг, чтобы полностью отделить модули от оболочки и друг от друга.

Это прекрасно работает в видах модуля. Но я не могу сделать это в файле модуля определения класса , так как ConfigurationManager недоступен на этом уровне.

Я могу сделать это, указав название региона в разделе ApplicatonSettings app.config модуля . Но это противоречит цели возможности хранить модуль в одном месте для загрузки несколькими приложениями. Он действительно должен находиться в app.config основного приложения .

Есть ли способ зарегистрировать View модуля в Region без жесткого кодирования названия Region в коде? Мы так стараемся, чтобы не кодировать что-либо. Это действительно необходимо здесь?

Ответы [ 2 ]

5 голосов
/ 14 сентября 2011

Как уже упоминал Мелеак в своем комментарии: используйте статический класс

namespace Infrastructure
{
    public static class RegionNames
    {
        public const string MainRegion = "MainRegion";
    }
}

В своем коде xaml вы можете использовать название региона следующим образом:

<UserControl 
    xmlns:Inf="clr-namespace:Infrastructure;assembly=Infrastructure"
    xmlns:Regions="clr-namespace:Microsoft.Practices.Prism.Regions;assembly=Microsoft.Practices.Prism">
    <ContentControl Regions:RegionManager.RegionName="{x:Static Inf:RegionNames.MainRegion}"/>
</UserControl>
3 голосов
/ 14 сентября 2011

Я понял. Оказывается, я был неправ в одном пункте, и я прошу прощения за это. Настройки родительского приложения .config доступны на уровне определения класса модуля. Нужно добавить правильные ссылки и сделать правильные записи импорта (или использования). Должно быть, я дремал у клавиатуры.

В app.config хост-приложения *1003* добавьте определения configSection. Здесь я определяю разделы для двух модулей:

<configSections>
    <sectionGroup name="Modules">
        <section name="SearchModule" type="System.Configuration.NameValueSectionHandler" />
        <section name="HeaderModule" type="System.Configuration.NameValueSectionHandler"/>
    </sectionGroup>
   ...
</configSections>

В app.config хост-приложения *1010* добавьте раздел Модули и подраздел для каждого модуля:

<Modules>
    <SearchModule>
        <add key="Region" value="SearchRegion"/>
    </SearchModule>
    <HeaderModule>
        <add key="Region" value="HeaderRegion"/>
    </HeaderModule>
</Modules>

В проекте модуля добавьте ссылку на System.Configuration.dll. Добавьте «Импорт» (VB) или «использование» (C #) для System.Collections.Specialized и System.Configuration:

VB:
Imports System.Collections.Specialized
Imports System.Configuration

C#:
using System.Collections.Specialized;
using System.Configuration;

В методе Initialize файла определения класса модуля:

VB:
    Public Sub Initialize() Implements Microsoft.Practices.Prism.Modularity.IModule.Initialize
        Dim settings As NameValueCollection = CType(ConfigurationManager.GetSection("Modules/SearchModule"), NameValueCollection)
        MyRegionManager.RegisterViewWithRegion(settings("Region"), GetType(SearchModuleView))
    End Sub

C#:
    public void Initialize() : Microsoft.Practices.Prism.Modularity.IModule.Initialize
    {
        (NameValueCollection)settings = (NameValueCollection)ConfigurationManager.GetSection("Modules/SearchModule");
        MyRegionManager.RegisterViewWithRegion(settings["Region"], typeof(SearchModuleView));
    }

Затем регистрируется представление с регионом из записей, сделанных в app.config приложения хоста. Это означает, что один модуль может быть построен для нескольких приложений хоста, и его можно вставить в область любого имени на хосте. Нет необходимости вносить изменения в скомпилированный код или создавать отдельный класс RegionNames для каждого приложения.

Наше приложение также построено с использованием архитектуры MVVM. Мы определяем View-Models в приложении Host и выставляем их модулям по именам, определенным в app.config с помощью RegionContext или EventAggregator. Теперь это полностью отделяет модули от приложения и делает модули полностью пригодными для повторного использования в различных приложениях без изменений.

Спасибо за вклад, и я надеюсь, что это поможет кому-то еще в будущем.

...