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