Advanced Binding Options

Introduction

Gum provides multiple options to control how binding behaves using the Binding type.

Using the Binding Class

The fastest way to set up binding is to use the name of the properties being bound, as shown in the following code example:

// Initialize
label.SetBinding(
    // UI property:
    nameof(label.Text),

    // ViewModel property:
    nameof(MyViewModel.LabelText));

The SetBinding call shown above is a shortcut for creating a Binding object. The following code is functionally identical:

// Initialize
// Binding is created using the ViewModel property
Binding binding = new(nameof(MyViewModel.LabelText));
label.SetBinding(
    // UI property:
    nameof(label.Text),
    binding);

The Binding instance can be modified by setting its properties on initializers. For example the following code shows how to update the binding to be one-way from the source (ViewModel) to the target (Label):

Lambda Binding

Binding can also be created using lambda expressions, which provide compile-time checking and refactoring support. Lambda expressions are extension methods available on FrameworkElement.

A typed lambda specifies the ViewModel type explicitly:

A parameterless lambda captures the ViewModel from a local variable:

Both approaches extract the property path from the expression at call time. The resulting binding behaves identically to a string-based binding.

Nested Property Paths

The Path on a Binding supports dotted paths to bind through multiple levels of properties. For example, if a ViewModel has a CurrentPlayer property which itself has a Name property, the binding can reach through both:

If any intermediate property in the path changes, the binding automatically re-evaluates. For example, if CurrentPlayer is replaced with a different object, the label updates to show the new player's name.

Lambda expressions also support nested paths:

Index-Based Binding

Binding paths support integer indexer access using bracket notation. This is useful for binding to a specific item in a list or array.

Indexes can appear at any position in a path:

Lambda expressions also support indexing:

If the collection implements INotifyCollectionChanged (such as ObservableCollection), the binding automatically re-evaluates when items are added, removed, replaced, or cleared. If the bound index is out of range, the binding uses the FallbackValue if one is set.

The following fiddle demonstrates index-based binding with a team of players. The TextBox is two-way bound to Players[0].Name, and three Labels display each player by index. Typing in the TextBox updates the first player's label, and the Replace button demonstrates collection change notification.

Try on XnaFiddle.NETarrow-up-right

Available Binding Properties

The following properties are available on the Binding class. Note that the term "source" typically refers to the ViewModel:

  • Path - the property path on the source. This can be a simple name like LabelText, a dotted path like Player.Name, or an indexed path like Items[0].Text.

  • Mode - the direction of data flow in binding. This can be used to create one-way binding.

  • UpdateSourceTrigger - controls when binding is applied

  • FallbackValue - the value to apply when binding cannot retrieve a value from the source

  • TargetNullValue - the value to use when the source property value is null

  • Converter - a converter to transform values between the source and target

  • ConverterParameter - an optional parameter to pass to the Converter

  • StringFormat - a format string to apply to the value

Converter Example

The Converter property accepts an IValueConverter implementation that transforms values as they flow between the source and target. The following example converts a boolean to a display string:

The converter is assigned through the Binding object:

When IsActive is true, the label displays "Yes". If the binding is two-way and the label text is set to "No", the converter's ConvertBack method sets IsActive to false.

StringFormat Example

The StringFormat property applies a format string when displaying source values. This is useful for formatting numbers, dates, or adding prefix text:

circle-info

When StringFormat is set, the binding effectively becomes one-way for display purposes. Setting the target value does not attempt to parse the formatted string back to the source.

FallbackValue Example

The FallbackValue is used when the binding path cannot be resolved, such as when an intermediate property is null or a collection index is out of range:

Last updated

Was this helpful?