如何在我的 Prism 应用程序(如 MS Office)中执行多个 shell? [英] How to do multiple shells in my Prism app (like MS Office)?

查看:11
本文介绍了如何在我的 Prism 应用程序(如 MS Office)中执行多个 shell?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试创建一个具有 MS Office 窗口行为的应用程序,例如 Word/Excel.用户打开应用程序,点击新建时,会出现一个全新的窗口,显示应用程序的外观.

I try to create an application that has a window behaviour as MS Office, for example Word/Excel. The user opens the application and when clicking new, a completely new window shall appear with the look of the application.

到目前为止我发现的最接近的是:链接

The closest that I found so far is this: Link

然而,这里的外壳是在应用程序启动时显示的.如何通过命令来做到这一点,或者可能有一种完全不同的方式来实现这一点?

However, here the shells are shown at application start. How to do this by command, or maybe there is a completely different way to achieve this?

我现在还发现了以下内容:链接,但在哪里以及如何调用此代码?

I have also found the following now: Link, but where and how to call this code?

推荐答案

创建多个 shell 是正确的想法.你只需要适当地处理细节.

Creating multiple shells is the correct idea. You just need to take care of the details appropriately.

当然,Prism 方法是让 DelegateCommand 处理新 shell 的创建.考虑到这个命令并不严格属于任何特定的 ViewModel(我会说它有一个应用程序范围的范围),我觉得有一个 public static class ApplicationWideCommands 和一个 CreateNewShellCommand 静态属性.然后,您可以使用 {x:Static} 从 XAML 绑定到它,或者根据需要从代码隐藏中执行它.

The Prism way is, of course, to have a DelegateCommand handle the creation of a new shell. Considering that this command does not strictly belong to any particular ViewModel (I 'd say it has an application-wide scope), it feels better to me to have a public static class ApplicationWideCommands with a CreateNewShellCommand static property. You can then either bind to it from XAML with {x:Static} or execute it from code-behind as needed.

这个命令需要处理两件事:

This command would need to take care of two things:

  1. 创建新的Window(实际上是一个Shell)
  2. 为新shell实例化一个新的IRegionManager,这样现有shell中的区域和新shell中的区域之间的区域名称就不会发生冲突
  3. 指示新 shell 中的区域属于新的 IRegionManager
  1. Create the new Window (actually, a Shell)
  2. Instantiate a new IRegionManager for the new shell, so that there is no conflict in region names between the regions in the existing shell and those in the new shell
  3. Instruct the regions in the new shell that they belong to the new IRegionManager

我会从后到先解决这个问题,因为它更容易解释.

I 'll tackle this last-to-first, because it's easier to explain.

在 Prism 中声明区域时,除了区域名称之外,您还可以声明要使用的区域管理器.通常你不需要这样做,但这里我们需要选择使用哪个 RegionManager 因为区域名称在单个区域管理器的范围内必须是唯一的.由于区域名称被硬编码在视图的 XAML 中,并且以另一种方式分配它们会很痛苦,我们需要更改等式的另一半:每个 shell 使用的区域管理器实例.所以在 Shell.xaml 里面可能有这样的东西:

When declaring a region in Prism you can declare the region manager to use in addition to the region name. Normally you don't need to do this, but here we need to choose which RegionManager to use because region names must be unique in the scope of a single region manager. Since the region names are hardcoded inside the XAML of the Views, and it would be a major pain to assign them another way, we need to change the other half of the equation: the region manager instance used by each shell. So inside Shell.xaml there might be something like this:

<ContentControl
  regions:RegionManager.RegionManager="{Binding RegionManager}"
  regions:RegionManager.RegionName="ExampleRegion"
/>

这将指示每个 shell 中的WorkspaceRegion"它属于绑定提供的 IRegionManager.由于shell通常没有DataContext,我们可以在shell类中声明RegionManager属性:

This will instruct the "WorkspaceRegion" in each shell that it belongs to the IRegionManager provided by the binding. Since the shell usually has no DataContext, we can declare the RegionManager property in the shell class itself:

public partial class Shell : Window
{
    public Shell(IRegionManager regionManager)
    {
        this.RegionManager = regionManager;
        InitializeComponent();
    }

    public IRegionManager RegionManager { get; private set; }
}

所以现在我们只需要确保每个 Shell 实例都有自己的 RegionManager.对于第一个"shell,这将由 BootStrapper 完成.(下面的代码使用DI容器解析对象,示例使用UnityContainer.如果你使用MEF进行依赖注入,只需在心理上转换为等效代码.)

So now we just need to make sure that each Shell instance gets its own RegionManager. For the "first" shell, this will be done by the BootStrapper. (The code below uses the DI container to resolve objects, and the examples use the UnityContainer. If you use MEF for dependency injection just mentally translate to the equivalent code.)

protected override DependencyObject CreateShell()
{
    // I am assuming you have a reference to the DI container
    var regionManager = this.Container.Resolve<IRegionManager>();
    return new Shell(regionManager);
}

对于其他 shell,将由 CreateNewShellCommand 完成:

For the other shells, it will be done by the CreateNewShellCommand:

private static ExecuteCreateNewShellCommand()
{
    // I am assuming you have a reference to the DI container
   var regionManager = this.Container.Resolve<IRegionManager>();
   ver newRegionManager = regionManager.CreateRegionManager();
   var shell = new Shell(newRegionManager);

   // The rest is easy, for example:
   shell.Show();
}

这里有一个重要的警告: RegionManager 作为单例注册到容器中.这意味着每当您解析 IRegionManager 您将返回相同的实例.为此,我们通过调用 IRegionManager.CreateRegionManager 方法(这适用于 Prism v4;我不确定 v2).

There is an important caveat here: The RegionManager is registered into the container as a singleton. This means that whenever you resolve IRegionManager you will be getting back the same instance. For this reason, we create a new instance by calling the IRegionManager.CreateRegionManager method (this applies Prism v4; I 'm not sure about v2).

此时,您知道如何创建任意数量的新 Shell 实例并相应地连接区域.

At this point, you know how to create any number of new Shell instances and wire up the regions accordingly.

您需要注意的最后一个细节是托管在每个 shell 中的所有区域,无论其可视化树有多深,都必须绑定到相同的 RegionManager.

The final detail you need to take care of is that all regions hosted in each shell, no matter how deep in its visual tree, have to bind to the same RegionManager.

这意味着您必须像我们在上面的 ContentControl 示例中那样为应用程序中所有视图中的所有区域显式设置区域管理器.幸运的是,这很容易完成,因为:

This means that you have to explicitly set the region manager to use like we did in the ContentControl example above for all regions in all Views in your application. Fortunately, this is done quite easily because:

  1. 所有视图最终都将成为可视化树中 Shell 的后代
  2. Shell 已经将正确的 RegionManager 作为属性公开,因此我们可以绑定到该属性
  1. All Views will end up being descendants of a Shell in the visual tree
  2. The Shell already exposes the correct RegionManager as a property, so we can bind to that

你会这样做:

<ItemsControl
  regions:RegionManager.RegionManager="{Binding RegionManager, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Shell}}}"
  regions:RegionManager.RegionName="AnotherRegion"
/>

一切就绪!

你现在应该准备好了.

All set!

You now should be ready to go.

这篇关于如何在我的 Prism 应用程序(如 MS Office)中执行多个 shell?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆