Struggling to understand MVVM architecture - c#

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.

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.

WPF, Prism, Autofac Wizard

I am tasked with creating a Wizard-Like application that has many Views (UserControls) to load and unload dynamically based on a workflow. From any point in the work flow, I need to be able to jump to another View. In concept, the Wizard will know what View to load next based on the actions performed inside the current View... much like a state-machine.
I am looking for some guidance as to how to get started. This is a WPF desktop application and the current plan is to use Prism and Autofac. I can be swayed in this plan but I'd need to have some good reasoning behind it.
Specifically, does Autofac follow the concept of a ServiceLocator? If not, how do I identify and load the next View?
I expect that my MainWindow will contain one ContentControl and the Content property will be bound to an "ActiveState" property that will hold reference to a ModelView that will be mapped to a View. This ActiveState property will then be changed based on where the workflow sends me.
Thanks in advance for your help.
Specifically, does Autofac follow the concept of a ServiceLocator?
Not sure what you mean, but Autofac supports the CommonServiceLocator. You do not want to use the service locator anti-pattern, though, do you?
If not, how do I identify and load the next View?
Identifying should be the job of your statemachine. Loading it is accomplished through IRegionManager.RequestNavigate. As a side note: you don't need to go view-first, you can also navigate to a view model and have the view as a data template (just in case you're like me and prefer control template + data template over user control).

How is MVVM in Xamarin.Forms/UWP/WPF any different from using code behind?

In learning Xamarin.Forms/UWP/WPF tutorials always tout MVVM as the design pattern of choice and I've followed suite, but I've never understood why. To contrast, in asp.net MVC the templated framework is used to great effect, Controllers deliver models to the view (HTML of some sort).
But in the Xamarin.Forms/UWP/WPF and others, we create a completely new class, ignore the code-behind file that cannot be removed and relegate it to telling our view where to look when binding data.
The only reason I could think of that makes MVVM better is if we could supply logic where different VM's could be 'injected' into the same view, maybe that would justify it.Though I have no idea how to do that.
Otherwise, how is creating a view model class better than using the code behind file? Is it really worse separation of concerns just because the view and code behind have the same name and are instantiated together?
MVVM pattern is much cleaner than using code-behind.
Separation of concerns
Imagine you have a view and a code-behind implemented. Now the business comes with a request to completely change the way the controls are presented - replacing them with new controls, changing layout and so on. Chances are, you will be forced to rewrite a lot of code just to satisfy the requirement, because the code-behind is directly tied to the view.
Now in case you have MVVM in place, you can easily swap the View part of the equation for any view which utilizes data binding to the right properties in a View model. You could easily present a single View model in several different ways - like creating multiple different views for different user roles while the view model stays exactly the same, you just choose what to display and how.
What view model actually creates is a middle layer between data and their presentation and makes it possible to more easily transform the data the view uses and change the presentation without affecting the view model if the interface is kept intact.
Data binding
Also if you are meaning purely code-behind without data-binding, the advantages of MVVM become even clearer. When you have a data-bound property that updates after user input in a TwoWay manner, for example if you have a form the user has to fill out, you don't have to remember to fetch the latest "changes" from the control using Text property, you know the latest version is already there in the data-bound property. In addition, you can add validation in the property setter, you can update other properties in the setter as well to orchestrate data handling in a much more abstract way than with code-behind approach, where you are tied to events and having to remember where the data come from and which specific controls and which specific properties you have to update. Imagine you display a given text in multiple places - with data binding you just set a single property and rely on {Binding} to display the text in all bound controls. With code-behind only, you need to remember which concrete controls display the text and when you add a new control, you have to update the code-behind appropriately, which is far less convenient.
Cross platform development
Another example would be having to develop a cross-platform application with native UI using MvvmCross. Here you can decide that some views or some functionality will not be available for certain OS or that you want to just implement it later. This is entirely possible - you just don't provide the UI for that functionality and the view model can stay the same.
View state
Finally - having all view state in code-behind means that when you navigate away, you must store the state somehow and restore it when navigating back because a new page is created. With MVVM you may decide to keep the view models of the navigation stack in memory and when navigating back just set the DataContext of the page to the existing view model instance to get back just in the same state as you left off.
Overall I see MVVM as a great pattern to improve flexibility of your codebase and it makes your solution more future-proof and resilient to changes.

MVVM design question

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.

Categories