🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
How to use vCurrent and “self” correctly in viewmodels
This page was created by Alexandra on 2017-05-26. Last edited by Wikiadmin on 2026-07-29.

You can build efficient master-detail ViewModels by using self to follow the object currently being rendered and vCurrent_<NestingName> to follow the item the user currently focuses.

Choose the right variable

A ViewModel expression is evaluated in a context. The variable you choose determines whether that expression follows each object in a list or follows one user-focused object.

Variable Meaning Use it when Example
self The object currently being rendered at the location of the expression. You are traversing an association from each parent object in a master-detail nesting. In the Months nesting beneath a Year, self.Months means the months of that rendered Year.
vCurrent_<NestingName> The current object in the named ViewModel nesting: the object the user most recently focused or clicked. One list must be filtered or otherwise controlled by the current item in another list. vCurrent_Years is the one Year currently focused in the Years nesting.

vCurrent_ is global to the running ViewModel. It does not change while the server iterates through a particular nesting. In contrast, self changes for every object rendered in that nesting.

For the complete list of predefined variables, including vSelected_ and selfVM, see Documentation:ViewModel variables and Documentation:Built in ViewModel variables.

Example: Year, Month, and Day

Assume a model with these associations:

  • A Year has Months.
  • A Month has Days.

The intended screen is a three-level master-detail view:

  1. Show a list of Years.
  2. When the user focuses a Year, show that Year's Months.
  3. When the user focuses a Month, show that Month's Days.

For example, when the user focuses 2015 and then March, the screen shows the months belonging to 2015 and the days belonging to March.

Recommended pattern: follow each rendered parent with self

Use the association from self in each detail nesting.

ViewModel nesting Collection expression What the expression means
Years The root collection of Year objects Render each available Year.
Months beneath Years self.Months For each rendered Year, render that Year's Months.
Days beneath Months self.Days For each rendered Month, render that Month's Days.

This is the SendAndShowSelected approach. It expresses the natural master-detail tree: each detail list belongs to its rendered parent. For a cursored ViewModel, the server can fetch and send the Years, the Months for the current Year, and the Days for the current Month. This is normally the smallest useful amount of data to send.

Why it works

When the server renders the Years list, self has a different value for each row:

  • While rendering 2014, self.Months is the months of 2014.
  • While rendering 2015, self.Months is the months of 2015.
  • While rendering 2016, self.Months is the months of 2016.

The same rule applies one level lower for Days. The nesting therefore remains correct whether the ViewModel is expanded sparsely or as a full tree.

Alternative: send the full tree, then show the current branch

You can also express a fully expanded tree and use the current selection only to decide what the user sees. This is the SendAllShowSelected approach.

With this approach, the server fetches and sends:

  • All Years.
  • All Months for all Years.
  • All Days for all Months.

Use it when the client needs the complete data tree up front, such as when a custom client component processes the data on the client. It can also be appropriate when a larger initial transfer is acceptable and later switches between branches should use data that is already on the client.

The cost is explicit: initial loading and transfer include every branch expressed by the ViewModel, not only the branch the user is currently viewing. Do not select this pattern only because a screen is master-detail; use the self-based pattern unless you need the full client-side tree.

Avoid using vCurrent_ as the parent of a repeated detail nesting

Do not construct the Months nesting beneath every Year from vCurrent_Years.Months. This is the SendWeirdAndShowSelected pattern.

Suppose the Years list contains 2014, 2015, and 2016, and the user has focused 2015. While the server iterates through the Years list, vCurrent_Years remains 2015:

Rendered Year row Incorrect Months expression Result
2014 vCurrent_Years.Months Months for 2015 are placed beneath the 2014 branch.
2015 vCurrent_Years.Months Months for 2015 are placed beneath the 2015 branch.
2016 vCurrent_Years.Months Months for 2015 are placed beneath the 2016 branch.

The visible branch can appear correct because the user sees the branch for the focused Year. However, the client receives repeated updates for incorrect hidden branches. This wastes work and data transfer, and it does not express the intended relationship. Replace the expression with self.Months.

Newer validation includes stricter rules for invalid recursive use of vCurrent_ further down a ViewModel tree. If such a rule identifies your expression, review whether the parent association should be evaluated from self. See Documentation:Breaking changes.

When vCurrent_ is the right choice

Use vCurrent_ when a list is controlled by a selection in another list but is not a detail association of each rendered parent.

For example, a ViewModel can contain a list of Years and a separate list that must show objects related to the currently focused Year. In that separate list's filter or collection expression, vCurrent_Years identifies the one Year selected by the user. The expression is not being evaluated once for every Year branch, so it does not duplicate the selected Year's data beneath unrelated Years.

vCurrent_ and vSelected_ are maintained for cursored ViewModels. vCurrent_ reflects the last focused item; vSelected_ is a collection used when multi-selection is enabled. For selection behavior, including automatic selection of the first grid row, see Documentation:VCurrent and vSelected.

Understand sparse and full ViewModel trees

When the server fills a ViewModel, it can build different amounts of the tree expressed by its nestings.

Tree form Server behavior Practical effect
Sparse tree Expands only the vCurrent_ branch at each level. Sends the currently relevant master-detail path rather than all possible branches.
Full tree Expands every object and branch expressed by the ViewModel expressions. Sends all data represented by the ViewModel tree.

For a WCF client with an ECO space in memory, sparse trees are built because the client has access to the full object space and can rebuild the ViewModel tree quickly after a user selection.

For Turnkey streaming ViewModel clients, including Angular Web UI and the WPF Turnkey client, the server builds full trees and streams them to the client. This makes correct use of self especially important: a repeated nesting based on vCurrent_ can cause every rendered branch to contain data for the same current object.

Do not use self in a ViewModel action

A ViewModel action acts on the view, not on one object being rendered in a nesting. Therefore, self is not available in a ViewModel action. Use the appropriate vCurrent_<NestingName> variable for the focused object, or the matching vSelected_<NestingName> collection when the action handles multiple selected objects.

For example, an action invoked from a Years grid should use vCurrent_Years to act on the focused Year, not self.

Read Documentation:ViewModel actions for the action context and available selection variables.

Checklist

Before you save a ViewModel, check each nested collection expression:

  1. Is this nesting a detail association of the object currently being rendered? Use self.
  2. Is this a separate list that depends on the one item the user focused elsewhere? Use the relevant vCurrent_ variable.
  3. Does the expression sit beneath a repeated parent list? Do not use that parent's vCurrent_ as though it changed for every rendered row.
  4. Do you need all branches on the client from the start? If yes, accept the full-tree transfer deliberately; otherwise prefer the selected master-detail branch.
  5. Is the expression in a ViewModel action? Use vCurrent_ or vSelected_, not self.

See also