-->

ModelView to ModelView communication

2019-08-03 22:17发布

问题:

Please, what do you suggest is the best (in terms of architectural quality) approach to the following scenario:

ModelViewA (parent) - requires collection from ModelViewB to display data - access collection multiple times even when the collection remains unchanged

ModelViewB (child) - holds collection of items. The collection conceptually belongs to ModelViewB and is primarily modified within this (model)view. However, ModelViewA can also modify the collection

The current approach I take is having collection in ModelViewB and a duplicate in ModelViewA. Using messaging bus (MMVM Light toolkit) I have the ModelViews notify each other of the change. However, this feels awkward since I have keep the duplicate collection and synchronize it. I would much rather have it only in one place and access it from both ModelViewA and B. I was thinking perhaps injecting one ModelView to another but that would increase coupling and generally feels wrong for MVVM pattern. I could also just use the static reference to both ModelViews since I have the static locator (also from MVVM Light toolkit) holding the references. Or perhaps there is a better solution?

Thanks,

O

回答1:

I'm (sort of) doing this right now.

I have a ConsoleViewModel which records and stores events from execution for display in the UI in my ConsoleView. Naturally, my ViewModels wish to communicate with this console so as to record their events.

In order to do this, I created an interface which exposes methods my ViewModels can use to write their events to the console.

public interface IConsole
{
  void Info(string message);
  void Info(string messageFormat, params object[] args)
  // etc
}

My ConsoleViewModel implements this interface, and all other ViewModels expose a public property of type IConsole which they use to write to the console.

In doing this, you can use many methods of compositing your ViewModels. You can use DI, or a simple service locator, or (as I have done), define them in a resource.

<Application.Resources>
    <ConsoleViewModel x:Key="ConsoleViewModel" />
    <DerpViewModel x:Key="Derp" 
        Console="{StaticResource ConsoleViewModel}" />
    <!--etc-->     
</Application.Resources>