ViewModel
No edit summary
m ((username removed) (log details removed))
 
(21 intermediate revisions by 3 users not shown)
Line 1: Line 1:
=== '''Example:''' ===
[[File:View_Model_PNG0.png|frameless|501x501px]]


Presented with a model I got from a colleague, that incidentally helps out as a Hockey referee when he is not coding, I wanted to create a ViewModel for the use-case “Set up new Hockey game”.
[[Category:View Model]]
 
[[Category:Beginner]]
[[File:Image 11 GAME.png|frameless|407x407px]]    
[[Category:The MDriven Book]]
 
=== Introduction to ViewModels ===
The Game class has a state machine:        [[File:Image 3 GAME.png|frameless|410x410px]]
The ViewModel in MDriven is a core piece of the Framework. The UML model contains all the information of the application but doesn't have clear perspectives or views of how that information should be used. It's a generalized bucket of data. The views, on the other hand, puts perspective on the modeled information.


I took a piece of paper and drew the UI I wanted to achieve:
[[File:ViewModel - image 1.png|frameless|650x650px]]


[[File:Image 4 GAME.png|frameless|370x370px]]
Views are used for several things in an MDriven Framework application.  The most common is the user interface of the application,  but others are creating APIs that are either read-only or read-right, the same way the user interface, a lot of times, is both read and write. 


Now I know what the requirements are on the ViewModel since I can see from the drawing what data the ViewModel needs to hold.  
The ViewModel is also used for extracting data either as JSON or XML or to create reports either as XML exports or by using the [[Creating reports for an application|report features]]. It can be merged into the output data of the view and merged into reports using ODS or ODT (Open Document Standard Format Documents). When the data is used that way from a ViewModel, each tag in the document is replaced by a piece of information from the ViewModel's structure. 


Then I created this ViewModel that I named GameSetup:
In general terms, the ViewModel unfolds a piece of your model and navigates through the different links and associations in your model to show some aspects of the application's data. 


[[File:Image 5.png|frameless|393x393px]]
ViewModels come in two distinct ways/formats - that is, the '''rooted''' and the '''unrooted''' ViewModel. 


Notice that it is just a series of named OCL expressions. Some expressions are nested to list other definitions like <code>Home_PickList</code> which states that if the game has a picked game type, then we know what teams can be chosen – namely those teams that are associated with that game type.
The unrooted ViewModels are used to find the data when the user is searching. They are called unrooted because they don't have a specific object in your database or model as their starting point. Instead, they are used to search or in other ways find objects by searching the database and showing that object or many objects in a list. 


I created some test data so that the UI can show something. My first attempt was to manually code a WPF UI and bind the values to the ViewModel:
The rooted ViewModels have a specific object as their starting point - for example, a person or something that is modelled specifically in your application. From that root object, the ViewModel, or the view navigates through associations to show things related to the root object. Nothing prevents a rooted view from showing any object in the database, but it's usually an object associated somehow with the root object.


The UI looks like this:
=== Parts of the ViewModel - Why are they called classes? ===
The ViewModel's different main parts are called ViewModel '''''classes'''''. Why "class"? You can think of the ViewModel as a definition of a new kind of objects, each of a new kind of class. If you think of your model as being made up of classes that define attributes, the ViewModel, in the same way, defines new classes of information that are constructed out of pieces from your main model.   


[[File:GAME UI.png|frameless|417x417px]]
The green background on the root ViewModel class.  


This has a minimal amount of fashionably acceptable styling. The good thing is that you can hand it to any WPF-savvy designer in the world – the data and rules are safe in the ViewModel.
[[File:ViewModel - image 2.png|frameless]] 


It already shows some of the good effects of separating UI from logic.
Blue background one the ViewModel classes that are usually linked to the green root ViewModel class.  
# The PickLists for Home and Visitor are filtered based on the type of game.
# The Picklist for the Home team filters away the Visitor team if set (and vice versa).
# The Start Game button is enabled only after both home and visitor are set.
# The End Game button is disabled until the game has started.
These are some examples of business logic that would have easily ended up in the UI if we did not have a good place to define it.


===== '''Taking It Further Still''' =====
[[File:ViewModel - image 3.png|frameless]] 
If the cost of creating and maintaining a ViewModel were high, fewer ViewModels would be created. Our mission is to reduce the cost of creating and maintaining them.


WPF is a declarative way to describe the UI. This means that the same basic look-less components like TextBlock, TextBox, CheckBox, Combobox, and Image, etc will be used again and again and they will be given a look by an external style or template.
The blue ones all define collections of data.  


What if we use this fact to provide some basic rendering/placing hints for the ViewModel columns? We could then use those clues to spill out the correct look-less control in the intended relative position; we would not need to mess about with XAML every 5 minutes. This is what the ViewModel-Editor looks like without rendering hints:
=== Rooted vs Unrooted ViewModels ===
The un-rooted name of a ViewModel refers to if the root ViewModel class has a root  - so a lot of "roots" here. In this case, it means that if there is a main model object, that is the ''context'' or ''self'' of the green view model root. In this case, you have "self" defined as an object in the main model.  That is different from this example where you don't have a root: 


[[File:View Model Further still.png|frameless|448x448px]]
[[File:ViewModel - image 5.png|frameless|330x330px]]


And this is the way it looks like when I have checked the “Use Placing Hints” checkbox:
That means there is no "self" from the context of the ViewModel root class. In this example, you can see that <code>Valuestore.allinstances</code> is used. ValueStore is a class and we can access all instances of that class in the database in the main model. By doing that, we get a collection of ValueStore objects that can be shown in the blue ViewModel class called ValueStore here. So the ValueStore ViewModel class has a context and therefore, it has "self", as in the example above. 


[[File:VM UI.png|frameless|453x453px]]
You use un-rooted view models to search or show a complete list of objects, or a partial list of objects, either just for showing or editing them. The classic use case is a [[Seeker view|Seeker]] where the user can input a search term and use the database search features to find objects.   


Given the extra fields for “Presentation”, “Column”, ”Row”, ”Span” etc, I can work the ViewModel – review to look like this:
Side note: the class of an unrooted ViewModel usually doesn't matter, but for ease of understanding from the developers perspective, it's usually set to tell what this view is used for. 


[[File:MV UI 2.png|frameless|450x450px]]
A rooted ViewModel if usually used to show some object properties from that object and relate information. For example, in ''this'' example, we have viewed "one thing". The "thing" is a modelled class from the main model - we show some attributes and then we show a list of details. We follow that association from "self" which is a "thing" to "details". 


Now, I really need to stress this so that I do not get misunderstood: We are not designing the presentation here at all. We are describing what data is available, which values are valid, possible selection lists of data, and, if the UI designer wishes to take notice of it, *''hints''* as to how to arrange the controls in relation to each other - which happens to give the option of generating the user-interface automatically by whatever front end is currently in fashion. This is all the natural information we have in mind while designing the ViewModel.
[[File:ViewModel - image 6.png|frameless]]


Having a ViewModel with placing hints, you can add a ViewModelWPFUserControl to your form with just one row:
So this evaluates to a collection of details and the blue ViewModel class has a context of detail, shows attributes connected to that ViewModel class, and therefore to attributes of the main model detail objects that are in this list.
<ecoVM:ViewModelWPFUserControl Grid.Row=”2″ x:Name=”VMU1″
  EcoSpaceType=”{x:Type ecospace:WPFBindingEcoSpace}”
    ViewModelName=”GameSetup” >
And the result is:


[[File:VM UI The game.png|frameless|392x392px]]
=== ViewModel class - Explained From a C# Perspective ===
As a side note, they can be generated into C# classes. You do this by selecting the CodeGen checkbox 


Remember that these auto layout controls also adhere to external set styles.
[[File:ViewModel - image 4.png|frameless|382x382px]] 


Having the ability to get simple UI automatically derived from the ViewModel, placing hints lowers the effort to produce and maintain. Experience has shown that a lot of the administrative parts of your application are left automated so that more time can be spent on the signature screens that are most important for your users.
and then each of these will be code generated and can then be used from C# as C# classes.


==== See also: ====
ViewModel classes from the perspective of C# traditional code would be to see each ViewModel class as an object with properties on it and those properties as a getter and setter that points to an object in the main model space. That way, when you read a property in a ViewModel class, you're actually reading from the backing object in your main model. When you're writing, the setter is executed and is setting something in the main model - that is how it's implemented in the MDriven system. If you have an expression that creates a list of objects, that property is a list in the .net runtime that references other ViewModel objects that are objects of the other ViewModel class which in turn has properties and each of those properties is backed by another main model object.
*[[Seekers and SearchLogic]]
*[[UIOverride]]
*[[Development info in runtime]]
*[[Edit in Grid]]
*[[ViewModel access and security]]
*[[Custom controls in ViewModel aided Views|Custom controls in ViewModel-aided Views]]
[[Category:View Model]]
[[Category:Beginner]]

Latest revision as of 05:32, 11 January 2024

Introduction to ViewModels

The ViewModel in MDriven is a core piece of the Framework. The UML model contains all the information of the application but doesn't have clear perspectives or views of how that information should be used. It's a generalized bucket of data. The views, on the other hand, puts perspective on the modeled information.

ViewModel - image 1.png

Views are used for several things in an MDriven Framework application.  The most common is the user interface of the application,  but others are creating APIs that are either read-only or read-right, the same way the user interface, a lot of times, is both read and write. 

The ViewModel is also used for extracting data either as JSON or XML or to create reports either as XML exports or by using the report features. It can be merged into the output data of the view and merged into reports using ODS or ODT (Open Document Standard Format Documents). When the data is used that way from a ViewModel, each tag in the document is replaced by a piece of information from the ViewModel's structure. 

In general terms, the ViewModel unfolds a piece of your model and navigates through the different links and associations in your model to show some aspects of the application's data. 

ViewModels come in two distinct ways/formats - that is, the rooted and the unrooted ViewModel. 

The unrooted ViewModels are used to find the data when the user is searching. They are called unrooted because they don't have a specific object in your database or model as their starting point. Instead, they are used to search or in other ways find objects by searching the database and showing that object or many objects in a list. 

The rooted ViewModels have a specific object as their starting point - for example, a person or something that is modelled specifically in your application. From that root object, the ViewModel, or the view navigates through associations to show things related to the root object. Nothing prevents a rooted view from showing any object in the database, but it's usually an object associated somehow with the root object.

Parts of the ViewModel - Why are they called classes?

The ViewModel's different main parts are called ViewModel classes. Why "class"? You can think of the ViewModel as a definition of a new kind of objects, each of a new kind of class. If you think of your model as being made up of classes that define attributes, the ViewModel, in the same way, defines new classes of information that are constructed out of pieces from your main model.

The green background on the root ViewModel class.

ViewModel - image 2.png

Blue background one the ViewModel classes that are usually linked to the green root ViewModel class.

ViewModel - image 3.png

The blue ones all define collections of data.

Rooted vs Unrooted ViewModels

The un-rooted name of a ViewModel refers to if the root ViewModel class has a root  - so a lot of "roots" here. In this case, it means that if there is a main model object, that is the context or self of the green view model root. In this case, you have "self" defined as an object in the main model.  That is different from this example where you don't have a root: 

ViewModel - image 5.png

That means there is no "self" from the context of the ViewModel root class. In this example, you can see that Valuestore.allinstances is used. ValueStore is a class and we can access all instances of that class in the database in the main model. By doing that, we get a collection of ValueStore objects that can be shown in the blue ViewModel class called ValueStore here. So the ValueStore ViewModel class has a context and therefore, it has "self", as in the example above. 

You use un-rooted view models to search or show a complete list of objects, or a partial list of objects, either just for showing or editing them. The classic use case is a Seeker where the user can input a search term and use the database search features to find objects.   

Side note: the class of an unrooted ViewModel usually doesn't matter, but for ease of understanding from the developers perspective, it's usually set to tell what this view is used for. 

A rooted ViewModel if usually used to show some object properties from that object and relate information. For example, in this example, we have viewed "one thing". The "thing" is a modelled class from the main model - we show some attributes and then we show a list of details. We follow that association from "self" which is a "thing" to "details". 

ViewModel - image 6.png

So this evaluates to a collection of details and the blue ViewModel class has a context of detail, shows attributes connected to that ViewModel class, and therefore to attributes of the main model detail objects that are in this list.

ViewModel class - Explained From a C# Perspective

As a side note, they can be generated into C# classes. You do this by selecting the CodeGen checkbox

ViewModel - image 4.png

and then each of these will be code generated and can then be used from C# as C# classes.

ViewModel classes from the perspective of C# traditional code would be to see each ViewModel class as an object with properties on it and those properties as a getter and setter that points to an object in the main model space. That way, when you read a property in a ViewModel class, you're actually reading from the backing object in your main model. When you're writing, the setter is executed and is setting something in the main model - that is how it's implemented in the MDriven system. If you have an expression that creates a list of objects, that property is a list in the .net runtime that references other ViewModel objects that are objects of the other ViewModel class which in turn has properties and each of those properties is backed by another main model object.

This page was edited 127 days ago on 01/11/2024. What links here