In a wpf application, a Model
object is created either from scratch or deserialized from some .xml
file. To create a connection to the ViewModel
, the following method (on the Model
!) is used by the application:
class Model
{
public override UserControl View
{
get
{
if (_view == null)
{
ViewModel viewModel = new ViewModel(this);
_view = new View();
_view.DataContext = viewModel;
}
return _view;
}
}
}
So far, so not mvvm. The Model
should not know (=have a direct reference to) the ViewModel
, let alone the View
.
(source: s-msft.com)
Breaking the pattern this way served as a convenient shortcut, but is starting to take a toll. I'd like to get rid of this method to separate the concerns properly as intended by the pattern.
But how would I do that? The functionality of the method in itself looks alright mmvm-wise. If I'd take it out of Model
and place it in the application, it looks like proper mvvm-ish code that wires up the components:
ViewModel viewModel = new ViewModel(new Model);
_view = new View();
_view.DataContext = viewModel;
But I cannot do that, because I do not know what Model
class I'm dealing with, when looking at the problem from the application point of view, because any one of several Model
classes might get instantiated or deserialized. In some sense, the Model
knows best what ViewModel
to use (hence the current implementation), but this is exactly the dependency that I'm trying to avoid.
How to build the parts of the mvvm pattern "against the grain" of the dependencies of the pattern? That is, going from Model
to View(Model)
and not the other way round.
- A simple solution might be to define a data structure in the application (e.g. a
Dictionary
) to associate a specificViewModel
that should be used with a specificModel
, but this means maintainance when adding more classes, making mistakes doing so, etc. - One could also build that association with reflection introducing a strict naming scheme like every
FooModel
will go together with aFooModelView
, which would be an improvement, but is still prone to breaking. - Or use some dependency injector thingy (e.g. mef) to automate the process of finding the pieces that belong together. But again, the dependencies seem to go the wrong way: The
ViewModel
might[Import]
anIModel
that theModel
could then[export]
, but theModel
(=the dependency) is created first, so I'd be looking for imports that would be satisfied with a given export and not the other way round. While such tools would help to split the concerns across even different assemblies (which is good and a goal, too), they don't solve the underlying problem that I don't know how to start this separation in the first place, which isn't their intended purpose anyway. If I swap import and export, my guess is that I'd end up with what I started with.
Are there any better solutions than building an association between the two (either by hardcoding it or reflection) in the application?
can you explain how and why each ViewModel doesn't already know the proper Model class to instantiate and the proper Model methods to call? Isn't that one of the primary reasons for having ViewModel classes in the first place?
Every ViewModel
knows the proper Model
class. I'm sorry if that wasn't clear from the text. In the code example, the Model
is passed to the constructor of the ViewModel
.
The ViewModel
does not instantiate the Model
object as this object might be constructed elsewhere (e.g. it could come from a deserialisation process).
That is indeed the primary reason for it to exist.
The problem is deciding what ViewModel
to create, so that the Model
(of a type that is decided at runtime) at hand can be passed to it.
Assuming you intend to use some form of IoC to solve this problem, couldn't you simply use the configuration of the DI container to identify the required model, or use a Service Locator?
Can you also further clarify the phrase, "Breaking the pattern this way served as a convenient shortcut, but is starting to take a toll"?
Given that the Model
itself ensured that the right ViewModel
(and View
) would be instantiated, the returned value could be carelessly added to the screen. The correct wiring of the components happened in the method seen in the first code example. So much for the convenience of being able to "display" a Model
. The toll to be paied is that Model
would use and therefore reference View
and ViewModel
, which are classes that depend on GUI libraries, which the Model
should not depend on.
or, to be blunt: Why does this console application need 5 dlls for graphical user interface components?
couldn't you simply use the configuration of the DI container to identify the required model, or use a Service Locator?
I guess the mentioned datastructure that associates ViewModel
with Model
is a (poor man's) Service Locator. I'm new to that pattern, but from a first glance that seems to be the case. Using the expected type of the ViewModel
s to build it is something I haven't thought about. (I'm thinking and not or regarding your question) As far as that approach goes, I'd take your suggestion as an answer. I was however hoping for a solution that's a little less DIY-ish. Seeing how binding does a lot of thing automatically, I'm somewhat surprised to find that going the opposite direction (that is, having a Model
to begin with) requires such manual dependency management. But then maybe this is what it takes.
Best Answer
Here are my suggestions:
Suggestion 1
You could try to use extension methods in order to separate concerns and in the end, perform exactly what you need (models that know their respective viewmodels):
Suggestion 2
You have different models that can arrive, that are resolved at runtime. In this option I suggest: