maui-data-binding

.NET MAUI Data Binding

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "maui-data-binding" with this command: npx skills add davidortinau/maui-skills/davidortinau-maui-skills-maui-data-binding

.NET MAUI Data Binding

Binding Modes

Mode Direction Use case

OneWay

Source → Target Display-only (default for most properties)

TwoWay

Source ↔ Target Editable controls (Entry.Text , Switch.IsToggled )

OneWayToSource

Target → Source Read user input without pushing back to UI

OneTime

Source → Target (once) Static values; no change tracking overhead

Set explicitly only when the property default doesn't match your intent. Do not specify Mode=OneWay on properties where OneWay is already the default (e.g. Label.Text , Image.Source ) — it adds noise without changing behavior.

<!-- ✅ OneTime overrides the default — be explicit --> <Label Text="{Binding Title, Mode=OneTime}" /> <!-- ✅ OneWayToSource overrides the default — be explicit --> <Entry Text="{Binding SearchQuery, Mode=OneWayToSource}" />

<!-- ✅ Defaults — omit Mode --> <Label Text="{Binding Score}" /> <!-- OneWay is the default for Label.Text --> <Entry Text="{Binding UserName}" /> <!-- TwoWay is the default for Entry.Text --> <Switch IsToggled="{Binding DarkMode}" /> <!-- TwoWay is the default for Switch.IsToggled -->

<!-- ❌ Redundant — these just restate the default --> <Label Text="{Binding Score, Mode=OneWay}" /> <Entry Text="{Binding UserName, Mode=TwoWay}" />

BindingContext and Property Paths

  • Every BindableObject inherits BindingContext from its parent unless explicitly set.

  • Property paths support dot notation and indexers:

<Label Text="{Binding Address.City}" /> <Label Text="{Binding Items[0].Name}" />

  • Set BindingContext in XAML or code-behind:

<ContentPage xmlns:vm="clr-namespace:MyApp.ViewModels" x:DataType="vm:MainViewModel"> <ContentPage.BindingContext> <vm:MainViewModel /> </ContentPage.BindingContext> </ContentPage>

Compiled Bindings

Compiled bindings resolve at build time, delivering 8–20× faster binding resolution than reflection-based bindings.

Enabling compiled bindings

Declare x:DataType on the element or an ancestor:

<ContentPage x:DataType="vm:MainViewModel"> <Label Text="{Binding UserName}" /> </ContentPage>

Where to place x:DataType

x:DataType should only be declared at levels where BindingContext is set:

  • Page root – where you assign BindingContext (in XAML or code-behind).

  • DataTemplate – which creates a new binding scope with a different type.

Do not scatter x:DataType on intermediate child elements. Children inherit the x:DataType from their ancestor, just as they inherit BindingContext . Adding x:DataType="x:Object" on children to "escape" compiled bindings is an anti-pattern — it disables compile-time checking and reintroduces reflection.

<!-- ✅ Correct: x:DataType only where BindingContext is set --> <ContentPage x:DataType="vm:MainViewModel"> <StackLayout> <Label Text="{Binding Title}" /> <Slider Value="{Binding Progress}" /> <GraphicsView /> </StackLayout> </ContentPage>

<!-- ❌ Wrong: x:DataType scattered on children --> <ContentPage x:DataType="vm:MainViewModel"> <StackLayout> <Label Text="{Binding Title}" /> <Slider x:DataType="x:Object" Value="{Binding Progress}" /> <GraphicsView x:DataType="x:Object" /> </StackLayout> </ContentPage>

DataTemplate requires its own x:DataType

DataTemplate creates a new binding scope. Always redeclare:

<CollectionView ItemsSource="{Binding People}"> <CollectionView.ItemTemplate> <DataTemplate x:DataType="model:Person"> <Label Text="{Binding FullName}" /> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView>

Compiler warnings

Warning Meaning

XC0022 Binding path not found on the declared x:DataType

XC0023 Property is not bindable

XC0024 x:DataType type not found

XC0025 Binding used without x:DataType (non-compiled fallback)

Treat these as errors in CI: <WarningsAsErrors>XC0022;XC0025</WarningsAsErrors> .

.NET 9+ compiled code bindings (SetBinding with lambda)

// 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());

IValueConverter

Implement IValueConverter with Convert (source → target) and ConvertBack (target → source):

public 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;

}

Declaring converters in XAML resources

<ContentPage.Resources> <local:IntToBoolConverter x:Key="IntToBool" /> </ContentPage.Resources>

<Switch IsToggled="{Binding Count, Converter={StaticResource IntToBool}}" />

ConverterParameter

ConverterParameter is always passed as a string. Parse it inside Convert :

<Label Text="{Binding Score, Converter={StaticResource ThresholdConverter}, ConverterParameter=50}" />

int threshold = int.Parse((string)parameter);

StringFormat

Use Binding.StringFormat for simple display formatting without a converter:

<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.

Multi-Binding

Combine multiple source values with 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();

}

Relative Bindings

Source Syntax Use case

Self {Binding Source={RelativeSource Self}, Path=Width}

Bind to own properties

Ancestor {Binding Source={RelativeSource AncestorType={x:Type vm:ParentVM}}, Path=Title}

Reach parent BindingContext

TemplatedParent {Binding Source={RelativeSource TemplatedParent}, Path=Padding}

Inside ControlTemplate

<!-- Square box: Height = Width --> <BoxView WidthRequest="100" HeightRequest="{Binding Source={RelativeSource Self}, Path=WidthRequest}" />

Binding Fallbacks

  • FallbackValue – used when the binding path cannot be resolved or the converter throws.

  • TargetNullValue – used when the bound value is null .

<Label Text="{Binding MiddleName, TargetNullValue='(none)', FallbackValue='unavailable'}" /> <Image Source="{Binding AvatarUrl, TargetNullValue='default_avatar.png'}" />

Threading

MAUI automatically marshals property-change notifications to the UI thread. You can raise PropertyChanged from any thread; the binding engine dispatches the update to the main thread.

// Safe from a background thread await Task.Run(() => { Items = LoadData(); // Raises PropertyChanged OnPropertyChanged(nameof(Items)); });

Caveat: Direct ObservableCollection mutations (Add/Remove) from background threads may still require MainThread.BeginInvokeOnMainThread .

Performance

  • Reflection overhead: Non-compiled bindings use reflection to resolve paths at runtime—measurably slower on large lists and startup.

  • Compiled bindings eliminate reflection; always prefer them.

  • NativeAOT / trimming: Reflection-based bindings may break under trimming. Compiled bindings (XAML x:DataType or code SetBinding with lambdas) are trimmer- and AOT-safe.

  • Avoid complex converter chains in hot paths; pre-compute values in the ViewModel instead.

  • Use OneTime mode for truly static data to skip change-tracking registration.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

maui-performance

No summary provided by upstream source.

Repository SourceNeeds Review
General

maui-rest-api

No summary provided by upstream source.

Repository SourceNeeds Review
General

maui-permissions

No summary provided by upstream source.

Repository SourceNeeds Review
General

maui-dependency-injection

No summary provided by upstream source.

Repository SourceNeeds Review