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.
Related
I’m refactoring a big view model and it's associated XAML page. I use Prism. The main page has a clear functionality, create an avatar. There are steps to create the avatar like take the picture, edit the picture, etc. I have now a detail side bar which controls the navigation for the steps and a main content area which I show different content depending on these steps. I hide/show the appropriate views depending on the step. The project grew and now I have a 2000+ line view model and a huge XAML file.
What I ended up doing after some research is creating ContentViews for each step (showing and hiding them for each step again), so the XAML get's modularized for each step and also a View Model for each step. I was successful in binding the ContentView to each ViewModel but now I have problems communicating the different View Models information.
As before everything was in the same View Model, all views could share the same bound properties if needed. Now, as each view model is independent I need to find a way to properly share this information. My first approach was to use the Messaging Center. This way I can send the information i need to share to the view model that manages the navigation between steps (NavigationViewModel) and this can send this information to the following view models.
The thing is that I don't really like this solution as I find it too complex and will end up with a lot of code in the NavigationViewModel to subscribe/send to each sub-viewmodel to pass the shared information.
So my question is, do you know any other way to ease the communication between the view models?
I even thought about using partial classes to 'hide' my big view model complexity, but I think this is not a good idea.
Recenlty i came across the same problem,my ViewModel became really huge(with hundreds of properties) .So what i did is :
Created an Interface class.Putting all the common properties in there.Let's say IA.
Created another class inheriting IA.
And now multiple classes are inherting IA,reducing the overall properties numbers.
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.
I'm trying to develop a WPF application - actually it's more a tool - using the MVVM pattern. I've read several articles, watched videos, posted questions but somehow I feel that my approach to or understanding of this MVVM thing is not "the right one".
I'll start from the UI. In a first stage the UI shall display the following:
Group box with
text box for the username
text box for the password (let's ignore the PasswordBox for the start)
Group box with
combo box for a list of project names available for this user (will be retrieved from a webservice)
button "Login" for logging in to the selected project
button "Logout" for logging out from the current project
So I would identify the following data that need to be handled:
A string for the username
A string for the password
An ObservableCollection<Project> for the list of projects
A Project object representing the active project
A boolean if logged in to a project or not
My worries, I have no idea how I should structure or design this following MVVM. How many views, viewmodels and models should I use here? Of course, the application will grow but not this much. Let's stick to the above.
There is no right or wrong answer to this
Think of Views, ViewModels, and Models as cut off points. They allow you to modularize your application versus taking a non-reusable monolithic approach.
In general, ViewModels to Views is 1:M however reality is that most of the time they are 1:1 relationship. The ViewModel and View are where the bulk of work resides, with the Model acting as nothing more than a POCO which implements INotifyPropertyChanged for binding needs.
In your example I would use a single View backed by a single ViewModel and multiple Models as is needed (Project, UserCredentials, etc...). You may have services which perform the actual login effort however you can perform that work in the ViewModel.
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 am using ViewModels with asp.net MVC3. One of the thing I am curious about is, suppose I have an entity named Customers and it has Add, Edit, Delete screens. Assume that they all have different properties requirements.
For eg. Add may have address field but the edit screen may not have edit screen, delete may only use customer name more than anything else.
My question is, how do you create ViewModels for this? Do you go with the approach of shared ViewModels between add, edit and delete i.e a single viewmodel class that handles all for you or do you prefer to create viewmodels classes / page?
Advantage with shared viewmodel is it reduces development time and we can reuse classes. But big problem with this is that if you are using tool like Automapper you may expected results for different screens.
Disadvantage with one viewmodel/page is that it increases development time. Which way should I go?
My approach to view models is to use shared view models until the requirements (the data transported) to the view is different. That means I'm using a shared view model for example for CreateAddress and EditAddress in case all data transported to the view is the same. In case an additional field needs to be displayed in the view for example in the CreateAddress view I'm refactoring my view models and using different view models for CreateAddress and EditAddress.
For example for DeleteAddress I'd use a distinct view model from start because I know that the data displayed in the DeleteAddress view is almost never the same as in Create/EditAddress.
Another approach is to use dynamic view models, since view models should/must not implement business logic and act as DTOs between controller and view this approach has some benefits (No need to create logic free, throw away DTOs).
It depends upon situation. if you have similar requirements for different screens (validation, properties to render etc.) you can use the viewmodel across different views. If there is difference of one or two properties, i would still use the same viewmodel and where these properties are not needed i will put them in hidden inputs so they travel back with the form post not allowing unwanted results. Hidden fields, as all know, can be tweaked and its upon developer to decide if it is safe to use hidden fields. However, if i have different validation requirements for two screens then i definitely have to go with viewmodel/page approach. You can mix both approaches according to requirements as they say "there is no best way of doing things"
All fields that exists in a model can be changed. It doesn't matter if they are hidden or not. All the user has to do is to inspect your pages and try to figure out what fields exist in the model.
Then he can add those fields (for instance with Chrome Dev Tools) to make changes to them.
The safest way to get rid of that problem is to just have models that only have the fields that are allowed to be changed.
That said, go ahead and use the same model if all fields in the model should be allowed to be changed by all users. (And simply do not show the fields that should not be modified)