Understanding Avalonia’s powerful data binding engine, binding modes, and value conversion
Avalonia’s data binding system connects UI properties to data sources, enabling reactive, declarative applications with automatic synchronization between views and view models.
<TextBlock Text="{Binding UserName}" /><!-- With explicit properties --><TextBlock Text="{Binding Path=UserName, Mode=OneWay}" /><!-- Binding to nested properties --><TextBlock Text="{Binding User.Profile.DisplayName}" />
using Avalonia.Data;// Create binding in codevar binding = new Binding{ Path = "UserName", Mode = BindingMode.OneWay};textBlock.Bind(TextBlock.TextProperty, binding);// Or use ReflectionBinding (Avalonia 12+)var reflectionBinding = new ReflectionBinding("UserName"){ Mode = BindingMode.TwoWay};
public class ReflectionBinding : BindingBase{ // The property path to bind to public string Path { get; set; } // Direction of data flow public BindingMode Mode { get; set; } // Binding source public object? Source { get; set; } // Value converter public IValueConverter? Converter { get; set; } // Converter parameter public object? ConverterParameter { get; set; } // Fallback value when binding fails public object? FallbackValue { get; set; } // Value to use when source is null public object? TargetNullValue { get; set; } // String format for display public string? StringFormat { get; set; } // When to update the source public UpdateSourceTrigger UpdateSourceTrigger { get; set; } // Delay before updating source (milliseconds) public int Delay { get; set; }}
<!-- Update on every keystroke (default) --><TextBox Text="{Binding SearchQuery, UpdateSourceTrigger=PropertyChanged}" /><!-- Update when control loses focus --><TextBox Text="{Binding UserName, UpdateSourceTrigger=LostFocus}" /><!-- Update explicitly via code --><TextBox Text="{Binding Value, UpdateSourceTrigger=Explicit}" />
UpdateSourceTrigger Values
public enum UpdateSourceTrigger{ Default, // Use property default PropertyChanged, // Update on every change LostFocus, // Update when focus lost Explicit // Update via UpdateSource() call}
using Avalonia.Data.Converters;public class FullNameConverter : IMultiValueConverter{ public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture) { if (values.Count >= 2 && values[0] is string first && values[1] is string last) { return $"{first} {last}"; } return string.Empty; }}
Use ObservableCollection<T> for collection bindings:
ViewModel with Observable Collection
using System.Collections.ObjectModel;using ReactiveUI;public class MainWindowViewModel : ViewModelBase{ public ObservableCollection<TodoItem> TodoItems { get; } public MainWindowViewModel() { TodoItems = new ObservableCollection<TodoItem>(); } public void AddItem(string title) { // UI automatically updates TodoItems.Add(new TodoItem { Title = title }); }}