我有一个简单的数据库应用程序,用户可以在其中添加或删除人员。此外,应用程序还有一个按钮"向应用程序添加新按钮" 。此应用程序使用Prism
框架构建。有两个模块:
RibbonControlModule (包含三个按钮 - Add Person
,Delete Person
,Add new button to application
)
PersonModule (包含添加和删除人员的逻辑)
我的要求是在运行时添加新按钮。
让我们想象一下情况。我住在华盛顿,我很满意这两个按钮(Add Person
和Delete Person
)。但我住在新泽西州的朋友鲍勃想要添加新按钮Edit Button
,而无需重新编译整个应用程序。也就是说,Bob在可以编辑人物的地方编写dll,然后点击Add new button to application
中的RibbonControlModule
。之后,EditPerson
按钮出现在RibbonControl
中,例如ContextMenu
。也许EditPerson
dll会是另一个Prism模块,我不知道。
也就是说,我的要求是:
是否可以使用WPF,MVVM和Prism?我真的很喜欢Prism并且不想否认Prism,但如果"最终证明了手段的合理性,那么我想使用其他技术。
如果有可能,那该怎么办呢?
答案 0 :(得分:3)
这就是MEF plugin architecture的设计目标。
简而言之,您创建了一个包含插件接口的SDK,并将其作为独立库提供给客户端。然后,客户端的插件将实现此接口,并使用MEF Export
属性将其导出,然后主应用程序将导入该属性。
它变得有点棘手的是数据模板,这通常是MVVM的关键组件。简而言之,您的插件需要将其数据模板放在资源字典中,为该字典提供自己的部分类文件,并使用MEF的[Export]
属性将其导出。然后您的主应用程序需要导入这些并将它们添加到全局ResourceDictionary的'MergedDictionaries'数组中。这通常与您在单独的传递中导入的所有视图模型类分开完成。实际效果是,您的插件可以在运行时提供视图和视图模型,以及将两者绑定在一起的数据模板,并且它们都可以像将它们静态编译到原始应用程序中一样工作。这也意味着您可以为客户创建插件API,而不会暴露主应用程序的内部。
这是一个非常复杂的话题,考虑到这个问题的一般性如何,如果这个问题没有被标记,我会感到惊讶。如果您想了解更多详情,请告知我们,我们可以将其移至讨论页面。
答案 1 :(得分:3)
您可以使用棱镜中的区域来执行您所描述的内容。您可以在功能区中添加一个命名区域,允许Prism模块在模块首次加载时将新按钮插入该区域,或者在用户单击模块的某个UI中的按钮时将其插入该区域。
为此,将ItemsControl添加到功能区中的某个窗格中,您希望插入的控件显示在该窗格中。将prism命名空间添加为XAML命名空间,如下所示:
xmlns:prism="http://prismlibrary/"
然后将以下附加属性添加到ItemsControl:
prism:RegionManager.RegionName="CustomModuleCommandRegion"
然后在您的模块中,如果在加载模块时应立即添加命令,则在模块类本身中注入IRegionManager,或者如果在加载特定视图之前它不会发生,则在ViewModel中的其他位置注入IRegionManager。像你描述的一些用户互动:
public ConstructorForModuleOrViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
}
private SomeCommandHandler()
{
var commandButton = // create button and wire up command here)
_regionManager.AddViewToRegion(commandButton, "CustomModuleCommandRegion");
}
您还可以选择使用区域管理器的RegisterViewWithRegion
方法设置工厂方法,或者只指定要注入的视图类型(即按钮)。但是对于一个按钮,您需要在将它放入区域之前(或之后)连接命令处理程序,因此AddViewToRegion
可能更合适。如果它是上下文敏感的东西 - 也就是说你只希望按钮显示在功能区中,或许在视图中进行选择时 - 那么你可以先从区域管理器获取该区域,然后使用{{1 Add
上的{}}和Remove
方法可以动态添加和删除视图(按钮):
IRegion
使用Prism模块和区域的组合,您可以实现应用程序的运行时可扩展性 - 即,这个新功能可能会被放入"无需重新编译应用程序中的主应用程序或其他模块。为此,您需要使用任一配置来指定模块,以便可以在部署环境中编辑以添加模块,或者可以使用DirectoryModuleCatalog在启动时扫描目录中的模块。它甚至可以使用FileSystemWatcher来监视应用程序运行时丢弃的模块的目录,并在放入监视目录时立即点亮它们。