我在设计可扩展程序的架构时遇到了一些问题。
我正在使用 MEF、MMVM Light Toolkit 和 AvalonDock。
第一个问题是如何显示使用 MEF 从另一个程序集中导入的某些
ViewModel
的视图。
为了解决这个问题,我导出 ResourceDictionary
,为该程序集中声明的视图定义 DataTemplate
。
Dictionary
:
<ResourceDictionary
...>
<DataTemplate DataType="viewmodels:MyViewModel">
<views:MyViewForViewModel/>
</DataTemplate>
</ResourceDictionary>
在
MainWindow
的构造函数中,我导入所有 ResourceDictionaries
并将它们与 MainWidow.ResourceDictionary
合并。
好吗?还可以指定 ResourceDictionary
的“范围”,以将其导入到 MainWindow
,而不是导入到 Application
。
第二个问题是
ICommands
和CommandBindings
。
为了填充 Menu
,我正在导出“MenuItems”,我在其中定义 ICommand
、Text
和其他内容,但我不知道如何导出 CommandBinding
,我是否应该在情况下使用 RelayCommand
当我无法创建CommandBinding
?
第三个问题是对话框。 我发现了很棒的文章 Showing Dialogs When Use the MVVM Pattern 并轻松地将其适应 MEF。但是,例如,我有一个没有任何视图的
IDatabaseService
。
Workspace
,主 ViewModel,存储 IDatabaseService
的实例并创建菜单项:Connect to Database
。使用 IDialogService Workspace 打开一些导入的 IConnectToDbDialog
,因此 Workspace
对此一无所知。当对话框关闭时, SqlConnectionString
应传递给 IDatabaseService
。
那么谁必须通过这个SqlConnectionString
,IConnectToDbDialog
,或Workspace
。
第四个问题是如何与
IDatabaseService
正确沟通。
例如。在某些视图中,我有Button
:“在数据库中创建项目”。单击按钮时我应该如何调用 IDatabaseService
方法 CreateItem(ElementType elementType)
?
问题是,有很多按钮在数据库中创建具有不同 Items
的 ElementType
,因此,我认为,创建一些带有参数的 ICommand
是正确的,并为此命令创建一个处理程序,该处理程序将调用IDatabaseService
中的一些方法。但我不知道怎么办。
另一种解决方案是从 IDatabaseService
向 ViewModel
发送消息来创建项目。
哪种方式更好?
尝试回答你的问题。
很好。您可以在 XAML 或代码隐藏上合并,但我更喜欢 XAML。您可以将其放在主窗口范围内的 MainWindow.Xaml 上,或者放在应用程序范围内的 App.Xaml 上。
我之前没有导出视图。在我看来,如果将 CommandBindings 放在 Menu 下,如果事件处理程序在导入环境的范围内,那么何时导出然后导入并不重要。
这取决于。理论上,您可以将服务调用放入所有者的视图模型或对话框的视图模型中。例如,如果您的对话框有一个创建/提交按钮,并且您希望对话框在提交成功之前保持活动状态,则将其放入对话框的视图模型中,以便在处理异常时可以保持其打开状态。如果您不需要对话框保持打开状态,那么您可以在对话框关闭后将逻辑放入所有者的视图模型中。
指挥更好。考虑到视图模型从 IoC 容器获取 IDatabaseService 对象,您可能有一个接受 ElementType 参数的 ICommand 属性,或者可以映射到 ElementType 的参数。在执行方法中,您调用 CreateItem 直接传递参数或从映射器传递参数。在 XAML 中,您将类型放入命令绑定中。有道理吗?
希望能帮到你。