Loading...
Loading...
Guidance for .NET MAUI XAML data bindings, compiled bindings, value converters, binding modes, multi-binding, relative bindings, and MVVM best practices.
npx skill4agent add davidortinau/maui-skills maui-data-binding| Mode | Direction | Use case |
|---|---|---|
| Source → Target | Display-only (default for most properties) |
| Source ↔ Target | Editable controls ( |
| Target → Source | Read user input without pushing back to UI |
| Source → Target (once) | Static values; no change tracking overhead |
<Entry Text="{Binding UserName, Mode=TwoWay}" />
<Label Text="{Binding Title, Mode=OneTime}" />BindableObjectBindingContext<Label Text="{Binding Address.City}" />
<Label Text="{Binding Items[0].Name}" />BindingContext<ContentPage xmlns:vm="clr-namespace:MyApp.ViewModels"
x:DataType="vm:MainViewModel">
<ContentPage.BindingContext>
<vm:MainViewModel />
</ContentPage.BindingContext>
</ContentPage>x:DataType<ContentPage x:DataType="vm:MainViewModel">
<Label Text="{Binding UserName}" />
</ContentPage>DataTemplate<CollectionView ItemsSource="{Binding People}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:Person">
<Label Text="{Binding FullName}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>| Warning | Meaning |
|---|---|
| XC0022 | Binding path not found on the declared |
| XC0023 | Property is not bindable |
| XC0024 | |
| XC0025 | Binding used without |
<WarningsAsErrors>XC0022;XC0025</WarningsAsErrors>// Fully AOT-safe, no reflection
label.SetBinding(Label.TextProperty,
static (PersonViewModel vm) => vm.FullName);
// With mode and converter
entry.SetBinding(Entry.TextProperty,
static (PersonViewModel vm) => vm.Age,
mode: BindingMode.TwoWay,
converter: new IntToStringConverter());IValueConverterConvertConvertBackpublic class IntToBoolConverter : IValueConverter
{
public object? Convert(object? value, Type targetType,
object? parameter, CultureInfo culture)
=> value is int i && i != 0;
public object? ConvertBack(object? value, Type targetType,
object? parameter, CultureInfo culture)
=> value is true ? 1 : 0;
}<ContentPage.Resources>
<local:IntToBoolConverter x:Key="IntToBool" />
</ContentPage.Resources>
<Switch IsToggled="{Binding Count, Converter={StaticResource IntToBool}}" />ConverterParameterConvert<Label Text="{Binding Score, Converter={StaticResource ThresholdConverter},
ConverterParameter=50}" />int threshold = int.Parse((string)parameter);Binding.StringFormat<Label Text="{Binding Price, StringFormat='Total: {0:C2}'}" />
<Label Text="{Binding DueDate, StringFormat='{0:MMM dd, yyyy}'}" />Note: Wrap the format string in single quotes when it contains commas or braces.
IMultiValueConverter<Label>
<Label.Text>
<MultiBinding Converter="{StaticResource FullNameConverter}"
StringFormat="{}{0}">
<Binding Path="FirstName" />
<Binding Path="LastName" />
</MultiBinding>
</Label.Text>
</Label>public class FullNameConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType,
object parameter, CultureInfo culture)
{
if (values.Length == 2 && values[0] is string first && values[1] is string last)
return $"{first} {last}";
return string.Empty;
}
public object[] ConvertBack(object value, Type[] targetTypes,
object parameter, CultureInfo culture)
=> throw new NotSupportedException();
}| Source | Syntax | Use case |
|---|---|---|
| Self | | Bind to own properties |
| Ancestor | | Reach parent BindingContext |
| TemplatedParent | | Inside ControlTemplate |
<!-- Square box: Height = Width -->
<BoxView WidthRequest="100"
HeightRequest="{Binding Source={RelativeSource Self}, Path=WidthRequest}" />null<Label Text="{Binding MiddleName, TargetNullValue='(none)',
FallbackValue='unavailable'}" />
<Image Source="{Binding AvatarUrl, TargetNullValue='default_avatar.png'}" />PropertyChanged// Safe from a background thread
await Task.Run(() =>
{
Items = LoadData(); // Raises PropertyChanged
OnPropertyChanged(nameof(Items));
});Caveat: Directmutations (Add/Remove) from background threads may still requireObservableCollection.MainThread.BeginInvokeOnMainThread
x:DataTypeSetBindingOneTime