Skip to content

Data Binding

Bob Dickinson edited this page Mar 30, 2015 · 1 revision

What is data binding?

Data binding is the mechanism that allows user interface elements in a "View" to be linked directly to data and/or commands in a "View Model".

Consider the following View and View Model:

View:

{ control: "stackpanel", orientation: "Horizontal", contents: [
    { control: "text", value: "First name:" },
    { control: "edit", binding: "firstName" }, // << Edit control bound to firstName
] },
{ control: "stackpanel", orientation: "Horizontal", contents: [
    { control: "text", value: "Last name:" },
    { control: "edit", binding: "lastName" }, // << Edit control bound to lastName
] },
{ control: "text", value: "Welcome {firstName} {lastName}" }, // << Text composed from bound values

View Model:

viewModel =
{
    firstName: "John",
    lastName: "Smith",
}

In this example, edit controls for first and last name will be pre-populated with the values "John" and "Smith" respectively, and the welcome string will be set to "Welcome John Smith". As the end user changes the value in either edit control, the associated value in the view model will be updated in real time, and that will trigger the simultaneous update of the welcome string.

In Synchro, data binding is the only method that applications have to populate and interact with user interface elements, and for that reason the Synchro data binding system is necessarily comprehensive (supporting literally every possible interaction).

Types of data binding

###Property Binding

  • Can be used in any attribute of any element
  • Multiple bindings can be aggregated in an attribute
  • One way (or one time using ^ notation)
  • Can use format specifiers, for example {screenSizeInches:F2} (formats as a fixed point number with two decimal places).

For supported format specifiers, see: http://msdn.microsoft.com/en-us/library/dwhawy9k(v=vs.110).aspx

###Value Binding

  • Can be used on certain elements
  • Specified in the "binding" attribute
  • Value binding (if any) is two-way, linked to a single data item in the view model
  • Zero or more bound commands

Binding Paths

Accessing view model data in a binding specification uses a path syntax. Consider the view model below:

viewModel = 
{
    person: 
    {
        firstName: "John",
        lastName: "Smith"
    },
    colors: 
    [
        { name: "Red", value: "FF0000" },
        { name: "Green", value: "00FF00" },
        { name: "Blue", value: "0000FF" }
    ],
    answer: 42
}
  • To access a simple value, use the property name, for example: answer
  • To access an object property, use dot notation, for example: person.firstName
  • To access an array element, use square bracket notation with a numeric (0-based) index, for example: colors[1]
  • These notations can be combined as required, for example: colors[1].name

The Binding Context

Each user interface element has a "binding context", provided by its container or parent element, which specifies the item in the view model on which its bindings will be based. At the top level, the binding context is the view model itself (as in the binding paths examples above).

Generally, the binding context for a given element is passed on to any child or contained element. However, some container elements modify the binding context passed their child or contained elements. For example, a list view element might create a binding context for each item in the underlying bound array, and pass those binding contexts to each child element (so each list item element is bound to a corresponding item in the array).

Elements can also alter their own binding context by using the foreach and/or with attribute in their binding specification. These binding context operations are applied before any property or value binding is processed for the element.

The foreach binding attribute creates an instance of the element for each instance of the array referenced by foreach. For example, using the View Model above:

{ control: "text", value: "Color: {name}", binding: { foreach: 'colors' } }

will yield three text controls, one for each color, each displaying the name of the color.

The with binding attribute selects a new context by applying the provided path to the current binding context. For example, using the view model above:

{ control: "text", value: "Hello {firstName} {lastName}", binding: { with: 'person' } }

will yield a text control with a welcome value using the first and last name from the 'person' property of the view model. Since with specified 'person', the binding context for the element was the person property, and the name values referenced are relative to that binding context.

It is possible to used both foreach and with in a single binding specification, using the foreach to select the context to be iterated, and then using with to further select properties of each iterated item to become the binding context.

Binding path tokens

It should be clear that each element has a binding context, and that that binding context can refer to any item anywhere in the view model. It is sometimes necessary to refer to values relative to either the root binding context (the view model itself) or the current binding context. The following binding path tokens allow for this:

  • $root - Selects the root of the view model.
  • $parent - Selects the parent of the current binding context.
  • $data - Selects the value of the current binding context.
  • $index - Produces a numeric value representing the position (zero-based index) of an iterated binding context

Future

Binding expression support

  • Simple negation using !, for example: visibility="{!isVisible}"
  • Mathematical, for example value="{(240 - charCount)}
  • Logical, for example: enabled="{(charCount >= 240)}"
  • Type conversion, for example: value="{str(240 - charCount)}"