Skip to main content

Advanced Binding Features

  • 5 minutes to read

Converters

Converters allow you to dynamically convert bindable property values.

Default Converters

The DevExpress MVVM Framework manages simple type convertions automatically. For instance, in the Binding via Default Converters demo, a string TextEdit.Text property is bound to the integer ViewModel Progress property. Here, the Framework converts property values from Int32 to String and back.

//View code
var fluent = mvvmContext.OfType<ViewModel>();
fluent.SetBinding(editor, e => e.Text, x => x.Progress);

//ViewModel code
public class ViewModel {
    public virtual int Progress { get; set; }
}

The MvvmContext component fires the BindingConvert event when the Framework converts values. You can handle this event to adjust the conversion logic. The Binding with Custom Conversion Handling demo illustrates a TextEdit editor whose EditValue property is bound to the integer ViewModel Value property. If a user leaves the TextEdit blank, the editor’s EditValue is null because automatic conversion cannot convert null to Int32. In this case, use the BindingConvert event handler to change null to 0.

//View code
var fluent = mvvmContext.OfType<ViewModel>();
mvvmContext.BindingConvert += (s, e) => {
    string strValue = e.Value as string;
    if(strValue != null) {
        int intValue;
        if(int.TryParse(strValue, out intValue))
            e.Value = intValue;
        else
            e.Value = null;
    }
    if(e.Value == null)
        e.Value = 0;
};
fluent.SetBinding(editor, e => e.EditValue, x => x.Value);

Custom Converters

When you use complex property types that cannot be converted automatically, you need to pass two converters as the last SetBinding method parameters. The first converter converts bindable property values to an acceptable type and the second converter does the opposite.

The Binding via Custom Converters demo illustrates a ViewModel with the ModelState property that accepts custom State enumeration values. This property is bound to the CheckBox.CheckState property whose type is System.Windows.Forms.CheckState. Lambda expressions in the SetBinding methods are converters that transform property values.

//View code
var fluent = mvvmContext.OfType<ViewModel>();
fluent.SetBinding(check, e => e.CheckState, x => x.ModelState,
    modelState => {
        // Convert the ViewModel.State to CheckState
        switch(modelState) {
            case ViewModel.State.Active:
                return CheckState.Checked;
            case ViewModel.State.Inactive:
                return CheckState.Unchecked;
            default:
                return CheckState.Indeterminate;
        }
    },
    checkState => {
        // Convert back from CheckState to the ViewModel.State
        switch(checkState) {
            case CheckState.Checked:
                return ViewModel.State.Active;
            case CheckState.Unchecked:
                return ViewModel.State.Inactive;
            default:
                return ViewModel.State.Suspended;
    }
});

//ViewModel code
public class ViewModel {
    public virtual State ModelState {
        get;
        set;
    }
    public enum State {
        Suspended = 0,
        Inactive = 1,
        Active = 2
    }
}

If users are not allowed to edit the View element’s property value, you can skip the reversed conversion.

Format Bound Values

To format bound property values, pass a string format expression to the SetBinding method. The {0} character sequence is a placeholder for the property value.

var fluent = mvvmContext.OfType<ViewModel>();
fluent.SetBinding(labelControl, l => l.Text, x => x.Value, "Bound property value is ({0})");

You can add Format Specifiers to apply additional numeric, date-time, and time span formats. The MVVM Best Practices demo illustrates how to display integer values as currency.

var fluent = mvvmContext.OfType<ViewModel>();
fluent.SetBinding(label, l => l.Text, x => x.Price, "Price: {0:C2}");

Bind Multiple Properties to the Same Control

To combine values of multiple properties within the same control, use the MvvmContext.SetMultiBinding method. This method accepts the following parameters:

  • a control name;
  • a control property that should be bound;
  • a string array populated with names of bindable ViewModel properties, whose values should be combined;
  • a format string (for non-editable controls) or a pair of converters (if users are allowed edit a bound control).

The DevExpress Demo Center provides two modules that combine values of the FirstName and LastName properties into one TextEdit editor. The module that uses a format string binds properties to a disabled (non-editable) editor. In the module that uses converters, you can change the TextEdit value and pass updated strings back to ViewModel properties.

Format string demo

var fluent = mvvmContext.OfType<ViewModel>();
mvvmContext.SetMultiBinding(
    editForFullName,
    e => e.Text,
    new string[] { "FirstName", "LastName" },
    "{1}, {0}"
);

Converters demo

var fluent = mvvmContext.OfType<ViewModel>();
mvvmContext.SetMultiBinding(
    editForFullName,
    e => e.EditValue,
    new string[] { "FirstName", "LastName" },
    values => string.Join(",", values),
    value => ((string)value).Split(',')
);