我尝试创建一个具有MS Office窗口行为的应用程序,例如Word / Excel。用户打开应用程序,当单击新建时,将出现一个全新的窗口,其中包含应用程序的外观。
我到目前为止最接近的是:Link
但是,这里的shell在应用程序启动时显示。如何通过命令执行此操作,或者可能有完全不同的方法来实现此目的?
编辑: 我现在也找到了以下内容:Link,但是在何处以及如何调用此代码?
答案 0 :(得分:33)
创建多个shell是正确的想法。你只需要妥善处理细节。
当然,Prism的方式是让DelegateCommand
处理新shell的创建。考虑到这个命令并不严格属于任何特定的ViewModel(我说它有一个应用程序范围),我感觉更好的是public static class ApplicationWideCommands
具有CreateNewShellCommand
静态属性。然后,您可以使用{x:Static}
从XAML绑定到它,或者根据需要从代码隐藏中执行它。
这个命令需要处理两件事:
Window
(实际上是Shell
)IRegionManager
,以便现有shell中的区域与新shell中的区域之间的区域名称不会发生冲突IRegionManager
我将从头到尾解决这个问题,因为它更容易解释。
在Prism中声明区域时,除了区域名称外,您还可以声明要使用的区域管理器。通常您不需要这样做,但在这里我们需要选择使用哪个RegionManager
,因为区域名称在单个区域管理器的范围内必须是唯一的。由于区域名称在视图的XAML中是硬编码的,并且以另一种方式分配它们将是一个主要的痛苦,我们需要更改方程的另一半:每个shell使用的区域管理器实例。所以在Shell.xaml
里面可能有这样的东西:
<ContentControl
regions:RegionManager.RegionManager="{Binding RegionManager}"
regions:RegionManager.RegionName="ExampleRegion"
/>
这将指示每个shell中的“WorkspaceRegion”属于绑定提供的IRegionManager
。由于shell通常没有DataContext
,我们可以在shell类本身中声明RegionManager
属性:
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进行依赖注入,只需在心理上转换为等效代码。)
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
:
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)。
此时,您知道如何创建任意数量的新Shell
个实例并相应地连接这些区域。
您需要注意的最后一个细节是每个shell中托管的所有区域,无论其可视树有多深,都必须绑定到同一个RegionManager
。 / p>
这意味着您必须显式设置区域管理器,就像我们在上面的ContentControl
示例中为应用程序中所有视图中的所有区域所做的那样。幸运的是,这很容易做到,因为:
Shell
的后代Shell
已经将正确的RegionManager
公开为属性,因此我们可以绑定到你会这样做:
<ItemsControl
regions:RegionManager.RegionManager="{Binding RegionManager, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Shell}}}"
regions:RegionManager.RegionName="AnotherRegion"
/>
你现在应该准备好了。
答案 1 :(得分:0)
这里是我现在用来创建多个带有多个EventAggregators的Shell的实现。我在引导程序中传递容器。在我的特殊情况下,子模块侦听事件以获取此Shell操作的路径参数。然后,子模块可以在路径位置创建节点数据文件,或者根据参数详细信息从路径位置加载。
public static class AppCommands
{
public static Container;
public static ICommand NewCommand = new DelegateCommand(CreateShell);
private static void CreateShell(object state)
{
var regionManager = Container.Resolve<IRegionManager>();
var newRegionManager = regionManager.CreateRegionManager();
var neweventAggregator = new EventAggregator();
Container.RegisterInstance<EventAggregator>(neweventAggregator);
var shell = new Shell(newRegionManager, neweventAggregator);
shell.Show();
SomeEventParameter parameter = new SomeEventParameter ();
//Add sth to the parameter here
neweventAggregator .GetEvent<SomeEvent>().Publish(parameter);
}
}