MVVM策略用于将数据加载到松耦合的视图及其视图模型/模型中。

3
我正在编写一个程序集,它将动态注入视图到WPF应用程序中定义的区域。我希望实现以下功能:
在应用程序中,我想能够将应用程序数据加载到作为视图底层的模型对象和视图模型中。
然后,我希望能够将模型数据保存在应用程序自己的数据存储机制中。
我最关心的是保持松散耦合的设计,以适应MVVM模式。我已经在我的应用程序中定义了一个区域,并且已经编写了程序集,以便适当的视图将被动态注入到该区域中。问题在于,就我所理解的而言,从应用程序的角度来看,视图可能是任何东西。此外,似乎不适合应用程序看到我为视图定义的模型或视图模型。
在MVVM中是否有针对这种情况的解决方案?哪种设计方式适合允许应用程序“某种方式”与我的模型通信?
视图也可能是多个:理想情况下,我希望有多个视图实例,每个实例提供模型实例的视图。应用程序应该能够随时将数据加载到所选模型中或从所选模型中读取数据。
如果我没有在帖子中包含足够的信息,我深表歉意——我试图让它足够通用,以避免项目的具体细节。如果需要,我很乐意澄清或提供更多信息。

2
如果你在这个网站上搜索MVVM,你会发现有33,193个结果(截至目前)...我非常确定你可以在那里找到所有关于MVVM的问题的答案。因此,我投票将此问题标记为重复。 - Sheridan
可能是[MVVM视图引用ViewModel]的重复问题(https://dev59.com/BnE85IYBdhLWcg3w8IQ4),还有许多其他类似的问题。这不仅仅是一个问题的重复,而是很多问题的重复。 - Sheridan
我认为这不仅仅是那些问题的纯重复,因为OP正在询问有关插件架构的问题。虽然这不纯粹是一个MVVM问题,但可能已经被问过了。 - Charleh
1个回答

1
为了让组件在壳体内部不需要任何通信,您需要将特定模块的所有逻辑(保存/加载等)放入该模块中。
然而,有可能在不耦合实现的情况下,让壳体与插件进行通信,尽管您可能希望在两者之间考虑一些共同机制。
最可能的是,您希望为壳体项目创建一个可扩展性框架库,其中包含一个常见的API,以便更好地集成您的插件。
MEF使得插件的发现/加载等非常容易。在设计插件样式框架时,接口是您的朋友。让您的插件实现特定接口意味着您的壳体可以与插件交互,同时对插件实际执行的操作不知道。
一个简单的例子可能是一个工具栏的命令集合(每个插件都可以向工具栏注册命令,根据可用命令动态创建按钮):
在您的可扩展性库中(壳体和插件都引用此库):
public interface IProvideCommands
{
    public IList<IToolBarCommand> AvailableCommands { get; }       
}

您可能也希望使用标记接口让外壳应用程序知道插件程序集中哪些ViewModel类型是应该加载到动态区域中的(在某种程度上,您已经做到了这一点,您是如何实现的?)
public interface IPluginShell { }

在您的插件主虚拟机中:
public class SomePluginViewModel : IPluginShell, IProvideCommands
{
    public IList<IToolBarCommand> AvailableCommands { get; private set; } // Populate this etc
}

在你的 shell 中:
public class ApplicationShell
{
    public ApplicationShell() 
    {
        // Load plugins
        ....
        // Discover commands
        var commandProvider = SomePlugin as IProvideCommands;

        if(commandProvider != null)
        {
            DoStuffWith(commandProvider.Commands);
        }
    }
}

命令随后取决于插件,它们可以决定哪些命令可用于 shell,而不是 shell 必须了解 VM 的任何信息。
如果有帮助,请告诉我。

嘿,感谢你的回复。这个问题在很大程度上是作为一个思维实验构建的,以便我和同事能够规划我们应用程序的架构。你给了很大帮助 - 我们意识到我们把需要处理的组件看作插件,而它更像是将功能添加到程序中的库(就像DevExpress或Telerik控件)。你提出的使用接口定义一切的建议正是我们需要讨论的:我们一直在避免使用接口,因为我们认为在应用程序中使用接口是错误的,但我们从未考虑过另一种方式。谢谢! - Michael Alexander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接