3
votes

I am working on an assembly that will dynamically inject a view into a defined region inside a WPF application, and I am trying to do accomplish the following:

In the application, I would like to be able to load application data into model objects underlying the view and its viewmodel.

I would like to then save model data within the application's own data storage mechanisms.

I am concerned most with maintaining a loosely coupled design that fits the MVVM pattern. I have defined a region in my application, and the assembly has been written such that the appropriate view will be dynamically injected into that region. The problem is, as I understand it, that the view could be anything from the application's perspective. Furthermore, it doesn't seem appropriate that the application see my model or view model for the view.

Is there anything in MVVM for such a scenario? What design would be appropriate to allow the application to somehow talk to my model?

The view may also be one of many: ideally, I would like to have multiple instances of the view, each providing a view of an instance of the model. The application should ideally be able to load data into or out of selected models at any given time.

I apologize if I have not included enough in this post - I am trying to leave it general enough to avoid specifics of the project. If asked, I would be happy to clarify or give more information.

1
If you search for MVVM in this website alone, you'll find 33,193 results (as of now)... I'm absolutely positive that you can find answers to all of your MVVM questions there. As such, I am voting to close this question as a duplicate.Sheridan
possible duplicate of MVVM View reference to ViewModel among many others. This is not so much a duplicate of this one question, but many.Sheridan
I'd say it's not just a pure dupe of those questions since the OP is asking about a plugin architecture. This isn't purely an MVVM question, though it probably has been askedCharleh

1 Answers

1
votes

In order for your components to sit in the shell without there being any communication between the two you would need to place all logic for a particular module (saving/loading etc) into that module.

However, it is quite possible to have a shell communicate with plugins without coupling the implementations, though you may want to consider having some common mechanisms between the two.

Most likely you will want an extensibility framework library for your shell project with a common API you can program against in order to better integrate your plugins

MEF allows you to do the plugin discovery/loading etc quite easily. Interfaces are your friend when designing a plugin style framework. Having your plugin implement a particular interface means that your shell can talk to the plugin whilst being agnostic to what the plugin actually does

A simple example may be a commands collection for a toolbar (each plugin could register commands with a toolbar which would create buttons dynamically based on what commands were available):

In your extensibility library (both shell and plugin references this lib):

public interface IProvideCommands
{
    public IList<IToolBarCommand> AvailableCommands { get; }       
}

You may also want a marker interface to let the shell app know which ViewModel types in the plugin assembly are the ones it should load into your dynamic area (you've done this to some degree, how did you achieve it?)

public interface IPluginShell { }

In your plugins main VM:

public class SomePluginViewModel : IPluginShell, IProvideCommands
{
    public IList<IToolBarCommand> AvailableCommands { get; private set; } // Populate this etc
}

In your shell:

public class ApplicationShell
{
    public ApplicationShell() 
    {
        // Load plugins
        ....
        // Discover commands
        var commandProvider = SomePlugin as IProvideCommands;

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

Commands are then at the mercy of the plugins - they can dictate which commands are available to the shell rather than the shell having to know anything about the VM itself.

Let me know if this helps