MVVM design question - c#

I'm trying to create an silverlight application using the MVVM design pattern. It's a kind of bank application.
I've watched a lot of tutorials on MVVM but something makes me real confused.
I have about fiwe usercontrols representing my views "TransactionsView", "AccountView" etc and a bunch of models "UserProfile" - containing user password, username and a list of UserAccounts, "UserAccounts" - containing name, balance and a list of AccountTransactions, "AccountTransactions" - containing a name, and ammount.
Should i create one modelview which contains my userprofile or should i create a viewmodel for every view i have? I'm a doing right so far? Or have i got it completley wrong?
Thanks

In MVVM, ViewModels are usually 1-to-1 with Views. There isn't a parity between number of ViewModel and Models, though.
View: UI
ViewModel: Handles changes to view state, forwarding them to the model if/when appropriate. Sends notifications from the underlying program back to the user. It may also do initial UI validation.
Model: Actual "guts" of the application. Algorithms, data storage, system calls etc go here. I put program flow here. I've seen other people put it in the ViewModel. That part is up to you to figure out.
A View always needs a ViewModel, hence 1-to-1 (it could have sub-models, but I'll leave that up to you to decide on/deal with. I'd start off with 1-to-1).
A ViewModel usually needs Models to actually "do work", but how many classes/instances is up to each app/problem you're trying to solve.

From what you explain you are going in the right direction. What viewmodel you create is a bit up to you, MVVM is not set in stone - its just a method. What I found through trial and ERROR was that it was smart to understand it well before digging myself in too deep.
I read many articles that didn't explain MVVM in a way I could understand. Finally I found a couple of articles by Jeremiah Morrill that were straight to the point and easy to understand: Article 1 and article 2.

One ViewModel per view is recommended for MVVM.

There's no real hard and fast rules but essentially there's normally one ViewModel per View. You can get into a situation where you want to share a view model across multiple views but it's rare.

Imagine what you want to see on the screen and each state the screen / controls on the screen might be in, everything that is needed on that particular screen (view) should have a corresponding property in your ViewModel that you can bind the View to. So, this translate to a single ViewModel for a particular View. The ViewModel itself can be tied into one or more model(s) in the back. At least that's how I understand it.

Related

How do I run a method from a relative ViewModel and get its return value?

To better show my problem, I drew a graph of how my ViewModel hierarchy looks like so far:
ViewModel hierarchy
What I want to achieve is simply call a method from ScriptEditorViewModel and ask it, if the object, which is currently being edited inside EditObjectViewModel has been specified in the script.
Later I also want to send some information to ScriptEditorViewModel and make it generate a script for the object if it doesn't exist.
ScriptEditorViewModel and ProjectManagementViewModel are 2 separate tabs in my program, which are basically operating at the same time.
Is it possible to do that and if so, is it a good approach?
Note: I'm currently using ReactiveUI as my MVVM framework but any other MVVM solution is also welcome.
When using MVVM pattern, you want to decouple components.
In View part there is xaml with bindings to data and command present in ViewModel.
In ViewModel you should keep data that is presented and logic that does something with that data. It is not the wisest thing to couple multiple ViewModels - keep their logic separated. If you have a command method, all data it deals with should be present in its ViewModel. For anything more complex, you shoud consider communicating with some kind of service or database.
Hence comes the Model part. Here you want to create the model of something you want to store and not necessary present in a View.
I don't know if I understood your problem well, but including a database or any kind of 'persistence layer' into your solution should resolve the problem of accessing specific information. You can create some in-memory storage for start.

Event-based communication between "sibling" views

I'm pretty new to WPF so I've been struggling with some basic concepts.
My application consists out of a main window containing various tabs. The first tab is used to add files, activating the other tabs which operate on the given files. For simplicity, let's call the latter "DataTabs".
I'm not sure about how to correctly communicate between the tabs. Currently, the FileInputTab uses a designated ICommand to do the following: Read the data, create a view model for the DataTab, and raise a "ViewModelReadyEvent" using the FileInputTab's view.
This event then bubbles up to the MainWindow, which activates the DataTabs and passes the created ViewModel on to them.
Now, two things I'm struggling with.
Populating the view model
Is it a better approach to populate the view model for the DataTabs inside their corresponding views, rather than from the FileInputTab that actually has nothing to do with it? This way, I could correctly establish a reference between the two, but I would have to perform the population separatly for every DataTab. Any thoughts?
Communication between "sibling" views
It doesn't feel right to let the event bubble up all the way to the MainWindow to let it orchestrate all inter-view communcation. I looked into RoutingStrategies, but I can't find any way to directly communicate between "sibling" views. I would like to raise an event in the FileInputTab and directly act on it in the DataTabs, without any intermediate.
Any thoughts, comments or book recommendations by WPF experts would be appreciated. Thanks in advance.
Using MVVM you could introduce a ViewModel for every tab. Then you could write a Service for the communication between the ViewModels. It is quite easy if you use the Messenger Pattern. One ViewModel sends a message to the Service and the Service leads it forward to the other ViewModel. The Service would also do the work, so your ViewModel would not have any business logic.
MVVM Light helps you a lot with the MVVM pattern.
You can use IEventAggregator to communicate between ViewModels.

The roles of the layers in MVVM

I know that in MVVM, we want to propagate user input from the view to the view model via data binding, and give the reflected view state in the view model to the model, where we write the business logic code, and update the user with the result via events.
However, does it mean that every change in the view must be done outside of the xaml.cs file?
Take for example a WPF application for sliding puzzle:
If we want to write an algorithm to solve the puzzle, we'll put the code in the model.
However, assume we want to update the grid after the user clicked the down key.
Checking if such move is possible, redrawing the board or giving the player any feedback (if the move is legit or no) should be done in the view? (the xaml.cs file)
More generally, are there "rules of thumb" to decide what to handle where?
Quick recap for the MVVM layers (or "rules of thumb"):
Model: Contains only the data used by the view models. As an exemple, consider business objects coming from database as "models".
View: Connection between the user and the view model. You can use multiple views for a same view model. If the view model changes and updates, the view should show the changes.
ViewModel: Contains the "business logic" between the view and the model. As such, commands, possible actions and algorithms are stored here. The view model dictates what is possible and what is not.
The communication between layers needs (that's the part necessary for MVVM) to be interchangeable, meaning the view model can be used with differents compatibles views and the model can be used by differents compatibles view models. To cut down on the dependencies of the multiples layers: the layers should not communicate directly between them. We use commands, events and direct bindings.
However, does it mean that every change in the view must be done outside of the xaml.cs file? [...] However, assume we want to update the grid after the user clicked the down key. Checking if such move is possible, redrawing the board or giving the player any feedback (if the move is legit or no) should be done in the view? (the xaml.cs file)
No. The view model should explicitly tell the view what is possible and what is not. The view shows that the action is possible or not: it does not decide if it is possible. Such decision is in the business logic, so in the view model.
As a trail of thoughts, take what it is said about interchangeable views. If you switch out the view foo for another view bar to show your puzzle and you did put the decision about "what's possible" in the view, you will have to rewrite the decision tree/algorithm in the new view bar and thus, duplication of code/logic.
When the decision is higher up, the view reflects what the view model is telling him. If the view model wants the view to "refresh" or to tell the user "hey, that's an illegal move", the view model will do so via commands and events. After receiving such events, the view could then decide what to do with it:
Show an error message about the illegal move
Show a tooltip that the move is illegal
Flash and shake the window with a beep to show that the move is illegal
Many more implementations...
I do hope I answered your question as thoroughly as possible.
My 10 cents:
If my experience have taught me anything, it's that it's almost impossible to fit all problems with the same, general solution.
In the case of MVVM, some things I've learned (the hard way):
It's easy for the view model to devolve into God classes (ie, mix of purely view-related logic + some business logic + etc..)
Depending on the application tiers, some times it makes sense for logic to work on view models; other times, it's better for logic to work on the models instead.
Whatever layers I/you/anyone think certain classes/logic should go, will most likely have to change as development progresses.
Instead, my approach is usually:
Prepare
Model (for serialization, very little logic),
View Model (with property change bindings for view) and
View (thin layer, binds almost directly to View Model)
Write the majority of the application logic in the View Model.
Easier to have logic in here, so view bindings can work
This is the stage where the View Model layer bloats up
When the application is finally working, begin refactoring
For rich-client applications, I find my Model classes to be almost purely data
The View Model will most likely be refactored into 2 layers: MVM (Model-View-Model) and VVM (View-View Model)
MVM: This is where common, business-related logic/objects sit
MVM Objects contain truly common properties that any view can bind to
VVM: This is almost a 1-to-1 replication of a WPF view
These objects are typically never shared outside its own view
The separation into MVM and VVM helps prevent a single view model class from catering to ever views' needs (ie. whole bunch of Is(Selected|Checked|etc) and *Command, that may be only used exclusively by one view).
(For some people, VVM logic could probably be part of the View. But for me, I often find myself eventually wishing I had separated them in the first place, for testing. So now I do.)
As the application evolves, properties/methods can be either pushed from the MVM into the VVM, or vice versa.
The application's hierarchy is almost never truly static.
Even when you build the best version of the application possible, the client will simply want more.
Having the know-how to refactor an existing architecture to accommodate new requirements > Designing an architecture that is flexible enough for any future requirements
having said all that, for many applications that aren't too complex, a slightly-bulgy View Model is usually good enough.

Should there be only one ViewModel class in MVVM pattern?

I am trying to understand the MVVM pattern and there is some issue that is not clear. My Xamarin Forms application will have several Views (which is quite obvious). Must everyone of them be binded to different ModelView class? Or maybe there should be only one MV?
Yes and No
Yes -> Basically the idea is that your ViewModel should only be used by one view. If you use a ViewModel to populate an area or whatever then that ViewModel is "reused" each time that view is presented in difference places.
No -> You can use multiple models in a view model. The purpose of the view model is to abstract away the business / data layer (i.e. the model).
However, using more than one model usually indicates that the view is too large. You might want to split it into user controls (which have their own view models).
References:
With MVVM, does each UI window have its own ViewModel?
In MVVM, is every ViewModel coupled to just one Model?
I've always thought of "each View has its own VM" - the model as being a sub-set of a comprehensive design.
I will say from painful experience: do not design models in isolation based solely on the view/UI they support. Without a comprehensive model back end you will have a hard time integrating all of the pieces into a coherent, complete business model that works. Anemic classes, redundant bits, incomplete and wrong validations, same properties-different names, incompatibilities w/ existing code, gobs of hacky glue code, Programmers breaking each other's code, no re-usability, no reuse of existing classes. For us it all came to a head in a 3 month test-fail-fix tilt-a-whirl of embarrassment.

Struggling to understand MVVM architecture

I'm trying to learn MVVM and WPF and I'm using the MVVM Light Toolkit. Here's what I'm not fully understanding and maybe it's due to an incorrect architecture of my UI.
What I'm trying to accomplish is pretty simple actually. This is a utility application by the way. I want a window that serves as the 'controller' so-to-say that has a set of buttons. Each button should change the content of a frame. Example: one button loads a 'screen' ( or a 'view' if you will ) that allows the user to configure an 'Agency' which is a custom object. Another button loads a list of Users from the Agency that was in the first 'screen'. This 'Users' view needs to also be loaded in the same frame. In fact, as of right now, the window with all the buttons really is only responsible for loading the 'screens' in the frame. The meat of the application will be within all the separate 'screens'
What I am not understanding is 1) how to let each screen/view know about each other since one is dependent upon the other. It seems that in MVVM the ViewModel shouldn't know about anything. But in my case, I need to pass information around ( such as my Agency ).
If I can get some hints on what I need to look into, that would be great.
Thanks!
Some ideas that might connect some of the dots:
You'll most likely have one viewmodel per view ("screen").
Each viewmodel will contain all of the logic for its corresponding view
Viewmodels can and will know about the models (Agency, Users)
Viewmodels can communicate with each other via the Messenger in MVVM Light
Think of MVVM Light's Messenger as an "application-wide eventing system". When you send a message out from one view model, any other view model can be listening for that message/event and react to it as needed.
Does that help at all? Keep your thoughts coming and I'll keep commenting and I'm sure the community will as well :)
Few things:
each of your screens, should be separate view (eg. user control or new window - I suppose you've done that already)
every part of model (eg. Agency, User) you want to display in your application, should be wrapped with its dedicated view model
your views don't really need to know about each other; you can use commands or events on view models to get rid of those dependencies
view model only needs to know about one thing: model it's building on
it's good to think about view as really simple class, with one single responsibility of rendering content; no logic, no code behind (unless it's purely UI/display related) is something to follow
You can try to prepare your models first (if you haven't done that already), then make view models for them (thinking what properties of models you want to expose to views) and once that's ready, build your views basing on view models. Other way around is also viable option - pick whichever feels more natural to you.
One more thing: since you mentioned you can display several screens in one (I assume) main area, think about equipping your view models with something along the lines of bool IsCurrentlyActive property. This way, you can easily show/hide views with button clicks and still utilize binding mechanism.
They shouldn't know about each other. That is what the Messenger is for controllers and views subscribe to the events they are interested in. That way they don't need to know or care where they event originated.
Hmm Kendrick is faster. What he said.
Also it sounds like you kind of want an Outlook type interface, some navigation that loads other views. I had the same question a while ago. How to do Regions in WPF without Prism?
To better understand the MVVM pattern look at this article: WPF Apps With The Model-View-ViewModel Design Pattern
Also I advice you to look at Caliburn Micro framework.

Categories