显示 Prism 区域中可用的模块

发布于 2024-10-11 01:54:37 字数 1724 浏览 3 评论 0原文

我想在我的应用程序加载时加载模块,并让它们将视图放入 区域(另请参阅这篇 MSDN 文章) 在 Shell(主视图)中。我目前正在按需加载一个模块,它工作得很好。 (我使用调用 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)]),当引导程序创建 Shell 时,我收到一个 ModuleInitializeException,提示“此 RegionManager 不包含名为“ContentRegion”的区域。”这告诉我,在 Shell 中创建区域和模块初始化存在计时问题。

所以这是我的问题:如何在发现时向 Shell 区域注册模块的视图,而不必使用 OnDemand 初始化并手动加载模块?

I want to load modules when my app loads and have them put their views in a region (see also this MSDN article) in the Shell (the main view). I am currently loading a module on demand and it works just fine. (I load the module with a button that calls this.moduleManager.LoadModule("ModuleB"); where moduleManager is defined as [Import(AllowRecomposition = false)] private IModuleManager moduleManager;. This all comes from the ModularityWithMef.Desktop sample application.) Here's the relevant code:

Module

[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 region

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

When I change to loading the module when available ([ModuleExport(typeof(ModuleB), InitializationMode = InitializationMode.WhenAvailable)]), I get a ModuleInitializeException when the bootstrapper is creating the Shell saying "This RegionManager does not contain a Region with the name 'ContentRegion'." This tells me that there is a timing issue with the creation of the region in the Shell and the initialization of the module.

So here's my question: How do I register the module's view with the Shell's region upon discovery and without having to use OnDemand initialization and manually load the module?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

染柒℉ 2024-10-18 01:54:37

嗯,这是一个简单的答案,但由于某种原因,我很难找到。 IRegionManager 提供了一个 RegisterViewWithRegion 方法,该方法采用返回视图的函数。这允许区域管理器在准备好时实例化视图(而不是使用立即发生的 AddToRegion)。因此,关键是在模块的 Initialize 例程中使用该方法:

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

在我弄清楚这一点的同时,我还想出了一个解决方法。当模块设置为 InitializationMode.OnDemand 时,Shell 可以导入 IModuleManager 并在 ContentRendered 中使用 LoadModule事件。这可确保该区域已添加到区域管理器中,并且模块可以毫无问题地添加其视图。如果您需要迭代可用模块,请使用此事件处理程序:

public Shell()
{
    InitializeComponent();

    ContentRendered += (o, eventArgs) =>
        {
            foreach (var moduleInfo in _moduleCatalog.Modules)
            {
                _moduleManager.LoadModule(moduleInfo.ModuleName);
            }
        };
}

Well this was an easy answer that was, for some reason, hard for me to find. The IRegionManager provides a RegisterViewWithRegion method that takes a function that returns the view. This allows the region manager to instantiate the view when it is ready (as opposed to using AddToRegion, which happens immediately). So the key is to use that method in the module's Initialize routine:

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

While I was figuring this out, I also came up with a workaround. When the module is set to InitializationMode.OnDemand, the Shell can import the IModuleManager and use LoadModule in the ContentRendered event. This ensures that the region has been added to the region manager and that the module can add its view without a problem. If you need to iterate through the available modules, use this event handler:

public Shell()
{
    InitializeComponent();

    ContentRendered += (o, eventArgs) =>
        {
            foreach (var moduleInfo in _moduleCatalog.Modules)
            {
                _moduleManager.LoadModule(moduleInfo.ModuleName);
            }
        };
}
没企图 2024-10-18 01:54:37

我倾向于在引导程序中快乐的视图和区域
AggregateCatalog.Changed _handler - 在这里您知道您的模块已经加载并且 Shell 已经使用所有模块实例化。

I tend to merry Views and the Region in the bootstrapper, in the
AggregateCatalog.Changed _handler - this is where you know that your module is already loaded and Shell is already instantiated with all the modules.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文