19

我正在构建一个演示应用程序来学习 Prism 4 的导航功能。该应用程序有两个模块——每个模块都有三个视图:

  • 带有文本块的用户控件(“欢迎使用模块 A”)
  • RibbonTab(使用区域适配器),以及
  • Outlook 风格的任务按钮(如 Outlook 的邮件、日历等)

Shell 具有三个命名区域:“RibbonRegion”、“TaskButtonRegion”和“WorkspaceRegion”。视图加载到这些区域。为了测试基本设置,我在 Prism 区域管理器中注册了所有三个视图,以便它们在启动时加载,并且都按预期工作。

接下来,我修改了设置,以便在启动时仅加载任务按钮。其他视图将仅在请求时通过单击任务按钮加载。我的模块初始化程序如下所示:

public void Initialize()
{
    /* We register the Task Button with the Prism Task Button Region because we want it
     * to be displayed immediately when the module is loaded, and for the lifetime of
     * the application. */

    // Register Task Button with Prism Region
    m_RegionManager.RegisterViewWithRegion("TaskButtonRegion", typeof(ModuleATaskButton));

    /* We register these objects with the Unity container because we don't want them
     * instantiated until we navigate to this module. */ 

    // Register View and Ribbon Tab as singletons with Unity container
    m_Container.RegisterType(typeof(ModuleAView), "ModuleAView", new ContainerControlledLifetimeManager());
    m_Container.RegisterType(typeof(ModuleARibbonTab), "ModuleARibbonTab", new ContainerControlledLifetimeManager());
}

当用户单击任务按钮时,它会调用一个 ICommand 对象,该对象调用IRegionManager.RequestNavigate()以显示视图:

public void Execute(object parameter)
{
    // Initialize
    var regionManager = m_ViewModel.RegionManager;

    // Show Ribbon Tab
    var moduleARibbonTab = new Uri("ModuleARibbonTab", UriKind.Relative);
    regionManager.RequestNavigate("RibbonRegion", moduleARibbonTab);

    // Show View
    var moduleAView = new Uri("ModuleAView", UriKind.Relative);
    regionManager.RequestNavigate("WorkspaceRegion", moduleAView);
}

单击任务按钮时正在调用该命令,但我得到的是:

演示应用屏幕截图

UserControl 显然加载为System.Object,我怀疑 RibbonTab 加载相同。我认为问题出在我的RequestNavigate()电话或我在 Unity 的注册上。但我无法确定问题所在。

任何人都可以阐明发生了什么吗?谢谢你的帮助。

4

1 回答 1

28

终于想通了这个。答案在Microsoft Prism 开发人员指南(第 4 版),第 120-121 页。它有两个部分:

首先,UserControlandRibbonTab对象从 Unity 解析为System.Object类型。这是 Unity 的一个限制,也是我用来注册视图对象的重载。要让它们解析为正确的类型,您需要为 使用不同的重载IUnityContainer.RegisterType()

// Register other view objects with DI Container (Unity)
m_Container.RegisterType<Object, ModuleAView>("ModuleAView");
m_Container.RegisterType<Object, ModuleARibbonTab>("ModuleARibbonTab");

此重载将 Unity 的本机System.Object分辨率映射到请求视图的正确类型。请参阅第 4 页上的注释。120开发人员指南

第二个问题没有在我的问题中明确说明,但它发生在我解决第一个问题时。RibbonTab当我切换到另一个模块时,我希望删除每个模块。由于我的功能区区域的行为类似于ItemsControl,因此两者RibbonTabs最终都被显示了——RibbonTab当我切换到模块 B 时,模块 A 没有被卸载。为了解决这个问题,我IRegionMemberLifetimeRibbonTab类上实现了。该问题已在第 4 页讨论。开发人员指南的第 121 条。

顺便说一句,我IRegionMemberLifetime在视图对象上实现了接口,而不是它们的视图模型,因为接口不会影响应用程序的后端,只会影响视图对象。

于 2011-03-01T00:17:47.627 回答