Log In
Home
Support
Demos
Documentation
Blogs
Training
Webinars
[Expand]General Information
[Collapse]WinForms Controls
  Prerequisites
 [Expand]What's Installed
 [Collapse]Build an Application
  [Expand]Choose Application UI
   Data Management Controls
  [Expand]Printing and Exporting
  [Collapse]WinForms MVVM
   [Collapse]Concepts
     Conventions and Attributes
     Fluent API Support
     Data Bindings and Notifications
     Commands
     Services
     Behaviors
     Layer Communication. Messenger
     View Management
     ViewModel Management
   [Expand]Design-time Support
   [Expand]Tutorials
  [Expand]Skins
  [Expand]Localization
  [Expand]Right-to-Left Layout
   Redistribution and Deployment
 [Expand]Controls and Libraries
 [Expand]Common Features
  Get More Help
 [Expand]API Reference
[Expand]ASP.NET Controls and MVC Extensions
[Expand]ASP.NET Bootstrap Controls
[Expand]ASP.NET Core Bootstrap Controls
[Expand]WPF Controls
[Expand]Xamarin Controls
[Expand]Windows 10 App Controls
[Expand]Document Server
[Expand]Reporting
[Expand]Report Server
[Expand]Dashboard
[Expand]eXpressApp Framework
[Expand]CodeRush
[Expand]CodeRush Classic
[Expand]Cross-Platform Core Libraries
[Expand]Tools and Utilities
 End-User Documentation

Data Bindings and Notifications

This document describes data bindings and notifications that alert the application when bound objects change their values.

  • Concepts - describes the traditional 'WinForms way' of data binding.
  • Base Classes - illustrates how to create bindable properties that support change notifications.
  • POCO Properties - introduces POCO (Plain Old CLR Objects) classes, supported by the DevExpress MVVM Framework.
  • POCO Dependencies - illustrates how to implement dependent properties that update their values when other related properties are modified.
  • Meta-POCO Bindings - explains how to move OnPropertyChanged callback declarations into separate metadata classes.
  • Collection Bindings - describes how to populate collections from the required source.
  • UI Triggers - explains how to use triggers to make separate UI elements to update their visual states in accordance with each other.
  • Legacy and Nested ViewModels - demonstrates how to work with child and legacy ViewModels.
  • Value Converters - this group illustrates how to convert bindable property values.
  • Formatting Bound Values - illustrates how to format bound values.
  • Binding Multiple Properties - shows how to bind multiple properties to the same UI element.

Expanded Concepts

The WinForms platform has embedded support for data bindings: to bind your control to the required data, you need to add the related binding to the Control.DataBindings collection. For instance, if you have an editor (for example, a text box) and a simple string Title property in your ViewModel, the standard code for binding looks like this:

In real-life applications, your UI element and its bindable property both must be able to update themselves at runtime. For example, the Title property from the code above should update its value if an end-user changes the text within the editor. To do so, a parent View Model must implement the INotifyPropertyChanged interface for your ViewModel classes.

The DevExpress MVVM Framework can assist you with creating and binding properties.

Expanded Base Classes

The first step in simplifying your code is to derive your ViewModels from classes declared in the DevExpress MVVM Framework: BindableBase and ViewModelBase. These classes already implement the INotifyPropertyChanged interface and allow you to shorten the code above:

Here, the bindable property is referred to using its string name. This approach can cause problems if the property is renamed - the compiler does not show any errors, and the control is not able to find the target property. The best way to accomplish this task is using POCO classes.

Expanded POCO Properties

MVVM Best Practices Demo

The text below has a related example in the DevExpress 'MVVM Best Practices' demo.

Group: API Code Examples
Module: Data Bindings
Example: POCO Bindable Properties
17.2 Demo Center: Launch the demo

The DevExpress MVVM Framework saves you a lot of time and lines of code, turning the above-mentioned code into this:

These simple classes with simple properties are called POCO (Plain Old CLR Objects). DevExpress MVVM Framework recognizes such classes and automatically upgrades them to something bigger. In the code above, the POCO class contains the string Title property. To allow the DevExpress MVVM Framework to make this property bindable, declare it auto-implemented and virtual. Binding these properties require a single line of code.

You can do the same using the Fluent API.

When working with POCO ViewModels, there is no need to implicitly create their instances. Instead, use one of the following approaches:

  • Use the DevExpress.Mvvm.POCO.ViewModelSource class's Create method as shown below.
  • Use the MvvmContext's ViewModelType property. The MvvmContext component is designed to create POCO ViewModels and ensures that your ViewModel refers all required interfaces to be able to use their features.

Expanded POCO Dependencies

MVVM Best Practices Demo

The text below has a related example in the DevExpress 'MVVM Best Practices' demo.

Group: API Code Examples
Module: Data Bindings
Example: POCO Dependencies
17.2 Demo Center: Launch the demo

The 'Simple Dependencies' example of the 'MVVM Best Practices' demo illustrates how to implement a dependency between two POCO properties. The two editors are bound to integer Operand1 and Operand2 bindable properties, which have associated On...Changed methods. Both methods call the UpdateResult method when an end-user inputs a value to either editor and changes the value of the related bindable property. The UpdateResult method re-calculates the third bindable property, Result. In turn, this property has an OnResultChanged method that updates the string ResultText property bound to the label. The code below illustrates code for this example.

Tip

The MaskProperties.MaskType properties of both editors must be set to MaskType.Numeric. Otherwise, bindings to integer Operand1 and Operand2 properties does not work.

The 'PropertyChanged notifications' is a similar example. Here, the [BindableProperty] data attribute is used to point to the NotifyResultAndResultTextChanged method that should be treated as the OnChanged method for both Operand1 and Operand2 bindable properties. This method calls the ViewModel's RaisePropertyChanged method to update property dependencies for the Result and ResultText properties manually.

Expanded Meta-POCO Bindings

MVVM Best Practices Demo

The text below has a related example in the DevExpress 'MVVM Best Practices' demo.

Group: API Code Examples
Module: Data Bindings
Example: POCO Meta-Declarations
17.2 Demo Center: Launch the demo

POCO classes eliminate many problems associated with manually creating and using property bindings and change notifications, except renaming properties. The Framework can relate the property and its On(PropertyName)Changed callback. However, when you rename the property, you should rename its related callback as well.

Use the Meta-POCO approach to overcome this issue. This approach is more complex than regular POCO classes, but also the most efficient since it grants maximum control over your app.

In the related demo example, you can find the same sample with Operand1 and Operand2 bindable properties used to calculate values for the integer Result and string ResultText properties.

Meta-POCO declaration is simple - create a nested class that contains metadata: expressions that specify explicitly which methods to use as property OnPropertyChanged callbacks. Metadata classes also allow you to make specific POCO properties unbindable. This nested class must implement the IMetadataProvider interface. The code below illustrates the ViewModel and its metadata declarations.

Using the BuildMetadata method, you can go over all ViewModel properties and provide each property's behavior. For instance, in the code below the Operand1 and Operand2 properties are treated as bindable properties that raise the OnPropertyChanged callback. This connection remains even when these properties are renamed. The Result property, in turn, is made non-bindable.

Note that this approach gives you the option to raise change notifications manually. For instance, the Result and ResultText properties did not receive their OnChanged callbacks within the metadata builder. You can still raise them manually:

Expanded Collection Bindings

MVVM Best Practices Demo

The text below has a related example in the DevExpress 'MVVM Best Practices' demo.

Group: API Code Examples
Module: Data Bindings
Example: Collection Bindings
17.2 Demo Center: Launch the demo

Many controls have item collections that should be populated from an external source and updated when this source changes. The code below illustrates the TestViewModel class that provides the Entities collection. This collection is the ObservableCollection object that stores the Test class instances, which expose two public properties (ID and Text). Additionally, the View Model declares two public methods to add new and remove existing records.

Using the MvvmContext component's API, you can populate a TileControl with tiles, one for each record within the Entities collection using the SetItemsSourceBinding method.
This method uses the following parameters:
  • Target - a target element that should be populated. A TileGroup in this example.
  • Items Selector - an expression that locates an items collection within the target. For this example, you need the TileGroup.Items collection.
  • Source Selector - an expression that locates a collection of items that should be used to populate the Target.
  • Match Expression - an expression that determines whether or not the data source item and the source element are the same. This expression is used when you modify an object within the Entities collection or remove it.
  • Create Expression - an expression that creates a new target element when the new source record appears. For this example, a new TileItem is created when a new Test class instance is placed within the Entities collection.
  • Dispose Expression - an expression that disposes of a target element when its related source collection record is removed.
  • Change Expression - when a new source collection record is added or the existing one is modified, the Match expression finds the target element related to this record. After that, you can use the Change expression to modify its properties. In this sample, the newly created TileItem receives the same caption as its related entity record.
When the binding is ready, you only need to call the collection's Add or Remove methods and the TileControl immediately adds or removes its TileItems respectively.

Expanded UI Triggers

MVVM Best Practices Demo

The text below has a related example in the DevExpress 'MVVM Best Practices' demo.

Group: API Code Examples
Module: Data Bindings
Example: UI Triggers
17.2 Demo Center: Launch the demo

Usually, when you have a check-box and a label that should say whether a check box is selected or clear, you would bind your check-box value to the IsChecked property, and define the OnIsCheckedChanged method that updates the LabelText property bound to your label. However, this method involves your ViewModel in a process: you have to define properties that would be bound to your UI controls. Avoid writing additional code in a ViewModel and utilize UI triggers when a process takes place entirely within a UI. Triggers update certain UI elements when another element changes, without using bindings.

Use the SetTrigger method of the MvvmContext component to set a trigger.

Note that in code above, the SetBinding syntax differs from the previous example. Instead of passing the bindable property as a simple string parameter, you define a source ViewModel and use the lambda-expression to obtain this property. This creates a fail-safe code that protects you from situations when the property is renamed, but the compiler shows no errors since the binding syntax is still correct.

With Fluent API, you can do the same but with fewer generic-parameters used.

Expanded Legacy and Nested ViewModels

MVVM Best Practices Demo

The text below has a related example in the DevExpress 'MVVM Best Practices' demo.

Group: API Code Examples
Module: Data Bindings
Example: Binding to Legacy ViewModels
17.2 Demo Center: Launch the demo

Although POCO-ViewModels provide many useful features, you might already have custom ViewModels (not built according to POCO concepts). If you switch to the DevExpress MVVM Framework, you do not have to modify them, since all the Framework features are still available.

You need to set the MvvmContext to this specific ViewModel type to work with legacy ViewModels.

When this is done, you can use data bindings. The syntax remains the same as before.

MVVM Best Practices Demo

The text below has a related example in the DevExpress 'MVVM Best Practices' demo.

Group: API Code Examples
Module: Data Bindings
Example: Data-Binding Capabilities (Binding Path)
17.2 Demo Center: Launch the demo

You can also bind your controls to properties from child ViewModels. First, define a ViewModel that serves as a nested ViewModel and optionally a property that retrieves this child model.

After that, you can use data bindings, specifying the bindable property as a part of the nested ViewModel.

The fluent API can be applied to create a fail-safe syntax.

Expanded Value Converters

MVVM Best Practices Demo

The text below has a related example in the DevExpress 'MVVM Best Practices' demo.

Group: API Code Examples
Module: Data Bindings
Example: Data-Binding Capabilities (Converters)
17.2 Demo Center: Launch the demo

In the POCO Properties section of this topic, the sample code binds the text editor to the string 'Title' property.

The EditValue property is an Object type and functions correctly when binding it to the string bindable property. However, there can be scenarios when the bindable property and the bound editor's property are a different type. In the demo center example, the integer 'Progress' property modifies the TrackBarControl and TextEdit controls' visual state. To do this, it is bound to the TrackBarControl.Value and TextEdit.Text properties. If the Value property is the same type as the Progress property (Int32), the 'Text' property is of a String type. However, same binding expressions are used for both editors.

The second binding works fine because of the default value converter. Whenever there is a type mismatch, the converter tries to find an appropriate replacement for the source type and cast it to this type. For instance, when you enter a value to the text edit, its string 'Text' property value is automatically converted to Int32 and can be passed to the integer 'Progress' property.

The default converter copes with most tasks when conversion is obvious and simple, like the Int32-String conversion in the example above. For more complex tasks, manually convert values using the SetBinding method overload that takes custom and reverse converters as the two last parameters.

Here, the custom value converter transforms the 'ModelState' property of the custom State type to the CheckState type, recognized by the check editor. The reverse converter casts the editor's check state back to the State enumerator value.

You can skip setting the reverse converter if you only need one-way value conversion. For instance, the second binding expression of the same demo center example binds the formatted 'ModelState' property, which is originally of the State type, to the string check editor's caption. Reverse conversion is not required because the caption cannot be modified manually.

Expanded Formatting Bound Values

MVVM Best Practices Demo

The text below has a related example in the DevExpress 'MVVM Best Practices' demo.

Group: API Code Examples
Module: Data Bindings
Example: Data-Binding Capabilities (Formatting)
17.2 Demo Center: Launch the demo

The code below illustrates how to bind a label control to the "Price" bindable property declared in the View Model.

Add a format string parameter to the SetBinding method to display the bound integer value as currency.

Expanded Binding Multiple Properties

MVVM Best Practices Demo

The text below has a related example in the DevExpress 'MVVM Best Practices' demo.

Group: API Code Examples
Module: Data Bindings
Example: Data-Binding Capabilities (MultiBinding)
17.2 Demo Center: Launch the demo

The code below illustrates how to use the SetMultiBinding method to bind the same editor to two bindable properties, "FirstName" and "Last Name".

You have to use converters to make two-way binding instead, so that changes made inside the editor are passed back to bindable properties. The code below converts separate bindable property values into a joint string and vice versa.

How would you rate this topic?​​​​​​​