what goes where?
This is a short description of my C# project:
I have a mechanical construction (only one in the whole program), described by some 20 to 30 parameters (deimensions, material parameters etc.), that may, as a complete set, come from an input screen or from an XML file (Deserialized). These parameters must then be processed in a calculation to generate output, that goes to a JPEG file and also to an HTML file.
The View is clear: it's the IO screen.
The View needs an ViewModel where the Properties are. Maybe:
My Model is the construction at hand, that is described by its parameters.
Those parameters however, are the same ones that are gathered from the IO screen , the View or from XML.
Some output (the JPEG file) also goes the View. It might be a Property that Notifies it's changed.
Now my question is, do I need a Model at all, because the ViewModel has all the properties already.
Or, do I need a ViewModel at all, because my Model has all the Properties to be Viewed. I could define a Model in the ViewModel (like it is always done in MVVM) and use the Model as a DataContext for the View. But that last option would make the View aware of the Model: not in the MVVM spirit.
I've written this multiple times already, but I'll do it once more...
The main reasoning behind MVVM is to separate layers and to avoid tight coupling as much as possible.
That said, View is, as you've correctly guessed, the UI. Things your user sees. It doesn't matter if it's a Windows, a Page, a custom control, webpage or even a console (when we talk about MVVM in a broader context).
ViewModel is a mediator between your model and the view. It takes, combines and manipulates your methods and properties from the model for the purposes of the View. It doesn't care how, when and where are these used. It also can trigger actions on the model side, for instance call services that take care of updating your database.
Model is EVERYTHING that isn't tied to the specific platform. It's classes of your business logic, it's database entities etc. It's basically your application stripped of any ties to the UI implementation. This is what people get wrong and think that model are only database entities. That's simply wrong!
To answer the question you've asked: "Now my question is, do I need a Model at all, because the ViewModel has all the properties already."
Yes, you should, otherwise you'll end up coupling the view directly to the model and that's violating MVVM principle. Your View shouldn't know ANYTHING about the model directly. As far as View cares, every one of the properties and methods can be coming from a different project. It won't change a thing and the view will still function the same.
You maybe don't see it yet, but in the future it will make your life much more easier. The code becomes easily maintainable if done correctly, much more readable etc.
In addition of what #walter said, you can check this Codeproject entry which explains flawlessly the difference and a little bit more. That article helped me to undestand when I was beginning:
http://www.codeproject.com/Articles/100175/Model-View-ViewModel-MVVM-Explained
In short:
Model: A class that represents data, it shouldn't do anything. It's good practice to implement INotifyPropertyChanged, however it's not required if you don't need to change the data from the View.
ViewModel: A class that exposes the model as a public property so that the view can bind to it. It should contain methods that interact with the model. It could also contain properties of it's own.
View: Binds to the ViewModel, where it can access the model, and ViewModel properties.
Related
I'm quite confused about the architecture of my MVVM application (formerly WinRT, now targeting UWP) concerning data access. I'm quite unsure how to propagate changes across the UI and where to put access to the data layer.
Here's the basic architecture:
Model layer: contains models that only have auto properties (no navigation properties that reference other models, just Ids; so they are basically just representations of the database). They don't implement INotifyPropertyChanged.
Data acccess layer: A repository that uses sqlite-net to store models in a database. It exposes the basic CRUD operations. It returns and accepts model from the model layer.
ViewModels:
ViewModels for the Models: They wrap around the models and expose properties. Sometimes I two-way bind content of controls (e.g. TextBoxes) to properties. The setters then access the data layer to persist this change.
PageViewModels for Views: They contain ViewModels from above and Commands. Many Commands have become very long as they do the data access, perform domain specific logic and update the PageViewModels properties.
Views (Pages): They bind to the PageViewModels and through DataTemplate to the ViewModels for the models. Sometimes there is two-way databinding, sometimes I use Commands.
I now have several problems with this architecture:
Problem 1: One model can be represented on the screen at several palaces. For example, a master-detail view that displays a list of all available entities of a type. The user can select one of them and its content is displayed in the detail view. If the user now changes a property (e.g. the model's name) in the detail view, the change should be immediatelly reflected in the master list. What is the best way of doing this?
Have one ViewModel for the model? I don't think this makes much sense, as the master list needs only very little logic, and the detail view much more.
Let the model implement INotifyPropertyChanged and thus propagate the change to the ViewModels? The problem I have with this, is that the data layer currently doesn't guarantee that the objects it returns for two read operations on one model id are identical - they just contain the data read from the database and are newly created when they are read (I think that's the way sqlite-net works). I'm also not really sure how to avoid memory leaks happening because of all the PropertyChanged event subscriptions from the ViewModels. Should I implement IDisposable and let the PageViewModel call its children's Dispose() method?
I currently have a DataChanged event on my data access layer. It is called whenever a create, update or delete operation occurs. Each ViewModel that can be displayed simultaneously listens to this event, checks whether the changed model is the one its the ViewModel for and then updates its own properties. Again I have the problem of the memory leak and this becomes slow, as too many ViewModels have to check whether the change is really for them.
Another way?
Problem 2: I'm also not sure whether the place I access data is really well chosen. The PageViewModels have become extremely convoluted and basically do everything. And all ViewModels require knowledge of the data layer with my architecture.
I've been thinking of scrapping data access with sqlite-net and using Entity Framework 7 instead. Would this solve the problems above, i.e. does it guarantee object identity for one model when I use the same context? I also think it would simplify the ViewModels as I rarely need read operations, as this is done through navigation properties.
I've also been wondering whether having two way databinding is good idea at all in a MVVM application, as it requires the property setter to call the data access layer to persist the changes. Is it better to do only one-way binding and persist all changes through commands?
I'd be really happy if someone could comment on my architecture and suggest improvements or point to good articles on MVVM architecture that focus on my problems.
Have one ViewModel for the model? I don't think this makes much sense, as the master list needs only very little logic, and the detail view much more.
ViewModel is not dependent on the model. ViewModel uses the model to address the needs of the view. ViewModel is the single point of contact for the view so whatever the view needs the viewmodel has to provide. So it can be a single model/multiple models. But you can break down a single ViewModels into multiple sub ViewModels to make the logic easier. Its like detail pane can be separated into a user control with its own view model. Your master page will just have the window that will host this control and the MasterViewmodel will push the responsibilities to the sub ViewModel.
Let the model implement INotifyPropertyChanged and thus propagate the change to the ViewModels? The problem I have with this, is that
the data layer currently doesn't guarantee that the objects it returns
for two read operations on one model id are identical - they just
contain the data read from the database and are newly created when
they are read (I think that's the way sqlite-net works). I'm also not
really sure how to avoid memory leaks happening because of all the
PropertyChanged event subscriptions from the ViewModels. Should I
implement IDisposable and let the PageViewModel call its children's
Dispose() method?
The danger is not using INotifyPropertyChanged, but as your rightly said its with the subcribing and unsubscribing. Wherever there is a need to subscribe to any event - not only INotifyPropertyChanged you need to use IDisposable to unsubscribe itself and its child ViewModels. I am not clear on the datalayer you describe, but if it publishes the property changed event for any modification I dont see any problem using INotifyPropertyChanged.
3.I currently have a DataChanged event on my data access layer. It is called whenever a create, update or delete operation occurs. Each
ViewModel that can be displayed simultaneously listens to this event,
checks whether the changed model is the one its the ViewModel for and
then updates its own properties. Again I have the problem of the
memory leak and this becomes slow, as too many ViewModels have to
check whether the change is really for them.
As I said earlier, if you handle the subscribe/unsubscribe properly for all models you need not worry about performance issue of INotifyPropertyChanged. But what might be adding to the problem is the number of calls you make to the database for requesting data. Have you considered using Async...Await for the data access layer which will not block the UI for any update thats happening. Even if the data update is slow a reactive UI which doesnt get blocked by the data calls is a better option.
So try adding a data access service which is abstracted over the DAL layer and provide a asynchronous approach to accessing the data. Also have a look at the Mediator Pattern. That might prove helpful.
I'm also not sure whether the place I access data is really well
chosen. The PageViewModels have become extremely convoluted and
basically do everything. And all ViewModels require knowledge of the
data layer with my architecture.
2 main problems i see,
If you feel the PageViewModel is too huge break down into sub view models of manageable size. Its very subjective, so you have to try to see what all parts can be broken down to its own component/usercontrol with its own viewmodel.
When you say ViewModels require knowledge of data layer, I hope you mean they are dependent on a Interface that manages the DAL layer services and doesn't have direct access to class with CRUD methods. If not try to add an abstract layer which does you actually do in your view model. And that will handle the DAL CRUD operations.
I've been thinking of scrapping data access with sqlite-net and using
Entity Framework 7 instead.
Don't try to replace sqlite-net with EF without hard evidence. You need to measure performance in your app before trying to jump into such big changes. What if the problem lies in your code rather than the component you are using. First try to fix the above mentioned issues then you can segregate the DAL layer via interfaces and replace it if needed.
I've also been wondering whether having two way databinding is good
idea at all in a MVVM application, as it requires the property setter
to call the data access layer to persist the changes. Is it better to
do only one-way binding and persist all changes through commands?
If you are making a call to database directly everytime you make a change to the field/ for every key stroke then its a problem. Then you should have a Copy of the Data Model and persist the changes only when you click the save button.
I'm currently creating a "wizard" to create new projects inside my program. I have a solution that is almost done but it doesn't feel "right" and start to think about other solutions. Maybe should note that I also use MVVMLight.
My current solution:
I have a window and the window contains custom user controls (they represent every page of the wizard).
Both the window and the user controls share the same view model
When you click back/next the view model handles which user control that should be visible
The problem with this one is that I don't like the shared view model. I have a shared view model because all pages configure different things on the same object and it's easier to follow. But at the same time thew view model contains a lot of things that each individuell user control doesn't need (for example only one page need methods to add/edit filters). It also makes it hard to re-user the user control later if I want them for something else than the wizard.
So should I instead create diffrent view models for the window and each user control and send messages between the view models with MVVMLights MessengerInstance? I feel that's cleaner but as a reader it's maybe harder to follow (something I feel in general when I sending messages around)?
With messenger it would be a workflow like this:
User enter all the information on a "page"
User click on next (that belongs to the window)
The windows view model have to send a message to the user control to check if all the data is valid
The user control check the data and have to send back if it's valid or not. If it's valid tell the next page to get visible, if not show error message.
So it would be a lot of messages back and forth that I don't need with the shared view model solution.
Or is there a better solution that I should do?
I would expect that the answers you receive here are primarily opinion based, but here goes anyway.
Currently, your view model has more than one responsibility, and therefore, more than one reason to change. It's certainly a good idea to split up your view models into smaller, more manageable classes. This may appear to reduce readability, however I would disagree. The idea of ensuring that classes only have one responsibility keeps things simple and promotes re-use.
That being said, your main view model will most likely hold references to many other child view models, but this isn't the end of the world, in fact, it's a good thing. The parent-child relationship between your view models is much like the parent-child relationship in your views. For example, a Window contains many UserControls, there's nothing wrong with mimicking this relationship with the view models.
Now, there are of course a few ways to communicate between view models. I personally prefer to use events, where a child view model raises an event that the parent view model subscribes to. Pretty simple, really. Although there is some degree of coupling in this scenario, you could of course abstract your classes away into interfaces and use dependency injection to inject them into the parent view model. Using events is down to personal preference, however MVVMLight has quite a nice MessengerInstance that decouples view models even further.
So. My suggestion:
Work out the responsibilities of your view model.
Split up the massive view model into smaller view models (based on the responsibilities).
Create a parent-child relationships between view models. Your view will in fact point you in the right direction in terms of the relationships.
So, I'm on to the next phase of my education and have reached a bit of a blocker related to my use of SQLite (this is for a universal app, with my current focus being on the Windows Phone side of that solution). My question is somewhat independent of SQLite but I will use it as an example.
I am looking at SQLite as the database for my app (based on various suggestions and comments here and elsewhere). Specifically, I am designing my view -> viewmodel -> model and I'm not sure of an appropriate pattern for passing around ObservableCollection.
Let me start at the model. I am making a call to SQLite-net's QueryAsync() method. So, buried deep in the model I have any await on the call to QueryAsync(). The method in which that lives (let's call it GetData(), for simplicity) is marked with async. So, that's the model.
Up at the view level I need to bind to a property of the viewmodel. Let's call that property GetDataVM(). Since it's a property I use a getter - and, as far as I can tell, I can't use await in getters. Is that true? Given the asynchronous call in the model - QueryAsync() - it seems I need an await, right?
I am sure I have some basic assumptions wrong here. But the basic principle I am trying to understand is what a control in my view must bind to when that property calls a method in the model that includes an async method.
I'm not finding this particularly easy to explain :) But, stepping right back, what I want is very simple, conceptually. I want a control to bind to a viewmodel property that, in turn, retrieves data from the model, which retrieves data from SQLite.
And I'm confused :)
Any help would be most appreciated (probably starting with clarifying questions about what the heck I'm trying to achieve :)).
Thanks.
I have an MSDN article on this topic.
The gist of it is this: as others have noted, a property read should be an immediate operation, whereas an asynchronous operation is (generally speaking) not immediate.
So, what you first need to do is decide what your UI will look like while the data is loading. When your VM loads, it should initialize its data in that "loading" state, and when the data arrives, the VM should update to the "ready" state (or to an "error" state if the operation failed).
In my MSDN article, I introduce a NotifyTaskCompletion<T> type that is pretty much just a data-binding-friendly wrapper around Task<T>. This allows you to do the state transitions via XAML bindings.
You are right, getters are not async. I would also refrain from trying a hack to make them work that way.
It is considered bad practise to have long running getters and good practise to wrap long running processes as await able asyncs.
You can see why the two are not compatible.
Instead, is it possible to trigger your async call from a command? That way you can make the call async and just assign the result to the property via the setter, that should call INotifyPropertyChanged PropertyChanged event to update your UI.
In general it is the ViewModel's responsibility to load the model (of course it could pass this responsibility to a repository class)
This way the ViewModel can contain the awaits and the Model can consist of plain data containing classes.
The View and ViewModel decide when to sync the model to and from the data source.
The role of the ViewModel is to mediate between the Model and the View. Most of the times I do not design the Model but accept it as a given from the data source and in many cases the Model is generated from a contract by a tool (Entity Framework, Web Services, ...) So I treat the Model as a dumb data container that changes when the data source changes.
The design of the View is driven by the user (requirements) so I am not in control of that either.
The ViewModel is where I get to design and code the transition between View and Model so that is also where I decide (based on user and technical requirements) when and how to load the data (Model) and transform it to match the structure needed by the View.
Many times the actual connecting to the data source is coded in a repository class so the ViewModel is not aware of the actual data source (connection/technology) This way it is easier to connect to another data source to support unit testing or the actual migration to another data source.
Try to put one responsibility in each class/layer.
I noticed that I have views that need the same information like others. But sometimes you need 5 properties of the view model and sometimes only 2.
Do you share such view model over many views or do you create a separate view model for each view or maybe do you prefere an inheritance or composition strategy?
For me there are some disadvantages for sharing view models:
Principle of Least Surprise: It is strange to fill only 2 properties of 5 of a view model and get null reference exception, because you don't want to query additional data of the database. When the view model has 5 properties I expect that all are filled. The exceptions prove the rule.
Separation of Concerns/Single Responsibility Principle: The view model cluttered up on complex sites, because you have to suit different needs for each view. If logic is involved its getting more complex, too.
What do you think? How do you handle such circumstances?
People tend to have different philosophies of ViewModels based on their perspective of their use. ViewModels are the glue between a view and a model and people will typically base their answer on which of the two ends they like to hold more rigid.
If you like your model/data objects to be more rigid, then you'll tend to tie the ViewModel closer to the model/data—i.e. you'll have a single ViewModel that is used in multiple views and let the ViewModel determine which properties to retrieve based on how you want to handle data loading (and defer things like images or other long-load properties, etc.).
If you like your Views to be more rigid, then you'll tie the ViewModel closer to the View—i.e. have a separate ViewModel for each view and let the model/data objects handle things like syncronization as you move from view to view.
Personally, I prefer the first as my data tends to be more rigid because it's less likely to change than the views are (in my projects—I don't think that's a universal property of data and views). Since change notifications are a natural feature of ViewModels, I don't have to make my model objects communicate changes if a user happens to have two views up that show the same/similar data.
In the project I am working on, each view has its own ViewModel, however we also have CollectionViewModels, which are shared/referenced by multiple view models.
Think - a list of Suppliers, that needs to be displayed in multiple screens in your application - and is bound to a variety of controls - a list box, grid view, whatever you need. Having just one ViewModel makes for simpler update/refresh logic of the list of Suppliers.
TLDR: I would only reuse view models, if all usage cases use the ViewModel in the same way. I.e. they all use the same properties etc.
I would have a seperate ViewModel for each view. Unused properties make the code less readable (Why is that property present if it isn't being used?). If you have the same functionality for a fixed set of properties over several views I could see using a base class which contains those properties.
Definitely one ViewModel per View, imho.
As your application grows in complexity shared ViewModels will tend to grow, and it doesn't feel great to pass an object with 50 properties to a View when all it needs is one property.
Also, sometimes you may want to add extra properties in your ViewModel that are absolutely specific to your View and that you don't need in other Views. Say you have a CSS class that depends on properties from the ViewModel. Instead of writing if else statements in your View, you create a property in the ViewModel that returns the correct css class based on whatever business rules you have. This way you make the View as slim as possible and with a dedicated ViewModel you are not sharing a CSS class name with Views that don't really care about it.
I usually share ViewModels. As I understand it, the advantages of using view models are (a) security, in that properties that should be hidden are and (b) separation of concerns between business and presentation layers. (b) is accomplished just the same while sharing view models.
As for (a), I'm rarely in a situation where exposing a property is a security risk in one place but not in another. If a property needs to be hidden, it probably needs to be hidden everywhere. Of course, YMMV, but this seems like a fairly subjective question.
I use Entity Framework with Code First so my domain classes need to remain pretty rigid as they will be mapped to a sql database.
Some views use just one directly mapped entity and that's just great so I use the same domain layer entity. If that entity requires more information (two password fields for example) I will use composition. 'Composition should be favoured over inheritance', so if you can use composition do so, usually as it's just additional properties, composition can be used.
If there is a screen that uses only two properties of that entity, or I want to hide properties due to security concerns, I create a new view model and only retrieve the necessary data. I will reuse view models but only if the same properties are required in that other view.
I would share a VM between multiple view only if all properties variables and methods are used by all the views otherwise I would use inheritance and abstract base view model and if this does not solve. Do 1 to 1
TLDR: Yes (if you really want to use it and know how to use it wisely).
I can think of three responsibilities wanted from view model layer:
coupling view layer & model layer together
offering interface for unit testing
separating logic into small pieces when a single page is complex
The first responsibility actually conflicts with the second.
Because once a view model knows (couples with) the view class to initiate,
it cannot be unit tested.
Knowing the model (and its provider) class to initiate doesn't cause this problem.
However if the provider is a singleton, the unit test become less "unit".
When comes to the third responsibility, there is a kind of logic that I call them routing.
For example, after clicking on a button, the user should see the next page.
Which layer is this kind logic supposed to lie in?
View? Model? Definitely NOT!
It has no where to go but view model.
Once a view model knows the class of the view model of the next page to initiate,
it makes a giant view model tree to be dealt with.
Because this happen recursively – the next page also knows the next next page.
No matter on which node in this view model tree,
once a change happens,
it reflects on the parent nodes.
How to deal with these reflections?
Subclassing?
Remember, in the tree, a node can have hundreds of direct / indirect child nodes.
Conclusion – view model is good at the third responsibility only if it drops the first.
The only one it is really good at is the second responsibility.
However, I see nobody mentioning it under this question.
I have separate library (Controls.DLL) with my custom Controls.
I have another library (Model.dll) with my data access code.
Some controls do need access to data. I'd like to keep those libraries loosely coupled. Basically, I'd like to acces data without referencing Model.dll
What is the proper way to do it? Naturally, I think Binding is a way to go. But it's not just binding to data, I also need to execute actions against my model (retreive data, paging, filtering). And I need to study metadata that my model contains.
For example, I have Customer class with properties like "FirstName", "LastName", etc. But I want those to be displayed inside my control with captions like "First Name", "Last Name". This is primitive example but it kind of shows my point.
My other idea was to have "providers" on data side that would spit out XML and on control side I will parse this XML. But how do I go about methods?
Another idea is to go with reflection. This way I would just pass object to Control. But I'm not as good with reflection and not sure if I can achieve things like: getting properties/attributes. Getting and executing methods? This sounds like a perfect thing to code with Interfaces but Interface need to live somewhere and therefore something have to reference something.
So, what is the best way to code loosely like this?
Check out the MVVM pattern (Model-View-ViewModel).
Basically, a ViewModel wraps a Model, and exposes data access and data manipulation commands to the user interface (the View) via property bindings.
You'll find heaps of documentation, tutorials etc. by searching for MVVM. Or check out this StackOverflow answer to get you started.
Update:
MVVM allows you to separate custom controls and data. It sounds like you want to dynamically generate interface components based upon data in your model. You can do this in MVVM (it's not the only way, of course). The view model can dynamically generate collections based upon the model. The view model can include methods for converting raw data to display data. This means neither your model or controls (view) need to know how to
do this.
Depending on the nature of your data, you may choose to have `generic' view models reflect over property names to procedurally generate display names (as in your primitive example), or you may choose to write specific view models for specific data in your model. That will depend upon the nature of your data. Either way, your custom controls (in the view) remain decoupled from the model.
Update 2:
Your view models do not need to live in the same assembly as the view (controls). You can even put them in a third assembly (as described here). Of course that encourages you to follow MVVM more strictly and make sure you have no dependencies from ViewModel to View, but that's a good thing. There are a few more hints on the issues related to hooking up views to view models you may encounter here.