Pavel Voronin
Pavel Voronin

Reputation: 13983

Where should ViewModel/View's properties be stored?

Simple example: I have VM with hierarchical item structure and I have designed View containing TreeView. Each tree node corresponds to data item related to the one in the Model. GUI must respect user preferences and settings and store different parameters including whether each particular node is expanded or not. As long as every node relates to some data we need to tie View settings with the Model. I beleive it's not OK to define property IsExpanded in the class standing for the Model.

So where should I store the settings so they stayed consistent with the data?

Upvotes: 3

Views: 440

Answers (3)

markmuetz
markmuetz

Reputation: 9664

I was in a similar situation, here's what I did to solve it.

Each ViewModel node had an IsExpanded property, which was bound to the TreeViewItem's IsExpanded property. I didn't want to persist the state of the tree by storing it in the Model in IsExpanded properties (it's to do with visual state right?). So instead, I had the VM tree structure generate a dictionary that stored the expansion state for each node against a string key generated from the node's state in the tree:

Dictionary<string, bool> treeExpandedStates

Each node in the tree had an ID, so in my case the key was something like "/1/3/7", but anything unique will do. This Dictionary was then serialized to a file on application close (in actual fact it was a SerializableDictionary). Then on application restart, it was deserialized and used to set the expansion state after the hierarchy had been loaded back up. This meant that the state of the tree was exactly as the user had left it, but nothing was stored in the Model.

Upvotes: 1

JOG
JOG

Reputation: 5640

I recognize the problem as a common dilemma in MVVM. I can look at it from two sides.

Approach A)

In the separation of View, Model, and ViewModel, what you describe resides in the Model. You write for example that it needs to be stored. That does not mean it is the same part of the model as the other model data.

Consider the following separation:

  • FolderModel - A model of the content or properties of a folder.
  • TreeNodeModel - A model of a users choices when exploring the tree view.

It might not be that easy to do a separation just like that, but the point is that MVVM is not meant to force you to stuff everything in the same place, and I do not think MVVM prevents you from keeping models for user interactions, the same way as you keep models for data content. Microsoft writes:

The data could come from a database, a Web service, a named pipe, a file on disk, or even carrier pigeons: it simply does not matter.

Why should not data for a data model be able to come from interactions of a user? :)

Approach B)

My usual approach to these dilemmas, though, is that properties like IsExpanded does mostly not need to be stored between sessions. That way, a property in the ViewModel, with a default value instead of a stored value, suffices. :)

And if it needs to be stored, it does not need to be stored in the Model. The ViewModel is for logic for presenting model data. If the ViewModel wants to save its logic state, that does not have to be stored in the Model.

Summary

In my point of view, you can store it any of these ways without breaking the MVVM pattern.

Upvotes: 1

Jonathan Allen
Jonathan Allen

Reputation: 70307

I believe it's not OK to define property IsExpaned in the class standing for the Model.

Why? Will there be occassions when the model is linked to two different tree-views?

If that is the case you can certainly create an "adapter view-model" that wraps your models and adds the property. Just be careful because that can technique can easily lead to a memory leak.

Otherwise, it is perfectly acceptable to put it right in the model, especially if that model is being used specifically to serve that view. As with all things, start with the simplest, most pragmatic approach.

Upvotes: 3

Related Questions