Отображение модулей в области Призма, когда доступно - PullRequest
2 голосов
/ 06 января 2011

Я хочу загружать модули, когда мое приложение загружается, и чтобы они помещали свои представления в регион (см. Также эту статью MSDN ) в командной консоли (основной вид). В настоящее время я загружаю модуль по требованию, и он работает просто отлично. (Я загружаю модуль кнопкой, которая вызывает this.moduleManager.LoadModule("ModuleB");, где moduleManager определяется как [Import(AllowRecomposition = false)] private IModuleManager moduleManager;. Все это происходит из примера приложения ModularityWithMef.Desktop .) Вот соответствующий код:

Модуль

[ModuleExport(typeof(ModuleB), InitializationMode = InitializationMode.OnDemand)]
public class ModuleB : IModule
{
    [Import(AllowRecomposition = false)] private IRegionManager _regionManager;

    /// <summary>
    /// Initializes a new instance of the <see cref="ModuleB"/> class.
    /// </summary>
    public ModuleB()
    {
    }

    /// <summary>
    /// Notifies the module that it has be initialized.
    /// </summary>
    public void Initialize()
    {
        _regionManager.AddToRegion("ContentRegion", new ModuleBView());
    }
}

XAML регион

<TabControl Regions:RegionManager.RegionName="ContentRegion" />

Когда я переключаюсь на загрузку модуля, когда он доступен ([ModuleExport(typeof(ModuleB), InitializationMode = InitializationMode.WhenAvailable)]), я получаю исключение ModuleInitializeException, когда загрузчик создает оболочку, говоря: «Этот RegionManager не содержит регион с именем« ContentRegion »». Это говорит мне о том, что существует проблема синхронизации создания региона в командной консоли и инициализации модуля.

Итак, вот мой вопрос: Как зарегистрировать представление модуля в области оболочки при обнаружении без необходимости использовать инициализацию OnDemand и вручную загрузить модуль?

Ответы [ 2 ]

2 голосов
/ 07 января 2011

Ну, это был простой ответ, который по некоторым причинам мне было трудно найти. IRegionManager предоставляет метод RegisterViewWithRegion, который принимает функцию, которая возвращает представление. Это позволяет менеджеру региона создавать экземпляр представления, когда оно готово (в отличие от использования AddToRegion, что происходит немедленно). Поэтому ключ заключается в том, чтобы использовать этот метод в подпрограмме Initialize модуля:

public void Initialize()
{
    _regionManager.RegisterViewWithRegion("ContentRegion", () => new ModuleBView());
}

Пока я выяснял это, я также нашел обходной путь. Когда для модуля установлено значение InitializationMode.OnDemand, оболочка может импортировать IModuleManager и использовать LoadModule в событии ContentRendered. Это гарантирует, что регион был добавлен в менеджер региона и что модуль может добавить свое представление без проблем. Если вам нужно перебрать доступные модули, используйте этот обработчик событий:

public Shell()
{
    InitializeComponent();

    ContentRendered += (o, eventArgs) =>
        {
            foreach (var moduleInfo in _moduleCatalog.Modules)
            {
                _moduleManager.LoadModule(moduleInfo.ModuleName);
            }
        };
}
0 голосов
/ 11 января 2011

Я склонен объединять Views и Region в загрузчике, в AggregateCatalog.Changed _handler - здесь вы знаете, что ваш модуль уже загружен, а Shell уже создан со всеми модулями.

...