All skills
davidortinau avatar

/maui-data-binding

@2fa0067
by David Ortinaudavidortinau/maui-skills173 stars
20

Guidance for .NET MAUI XAML data bindings, compiled bindings, value converters, binding modes, multi-binding, relative bindings, and MVVM best practices. USE FOR: "data binding", "compiled binding", "value converter", "IValueConverter", "binding mode", "TwoWay binding", "multi-binding", "relative binding", "BindingContext", "MVVM binding", "INotifyPropertyChanged". DO NOT USE FOR: CollectionView item templates (use maui-collectionview), Shell navigation data passing (use maui-shell-navigation), or dependency injection (use maui-dependency-injection).

Use this Skill: https://skilld.dev/gh/davidortinau/maui-skills/maui-data-binding

This session only. Nothing lands on disk.

SKILL.md

β‰ˆ144 tokens always: the name and description. β‰ˆ963 when used: this file. β‰ˆ1k more on demand in 1 file.

.NET MAUI Data Binding

Don't specify redundant binding modes

Set Mode explicitly only when overriding the default. Most properties already have the right default:

<!-- βœ… Defaults β€” omit Mode -->
<Label Text="{Binding Score}" />           <!-- OneWay is the default -->
<Entry Text="{Binding UserName}" />        <!-- TwoWay is the default -->
<Switch IsToggled="{Binding DarkMode}" />  <!-- TwoWay is the default -->

<!-- βœ… Override when needed -->
<Label Text="{Binding Title, Mode=OneTime}" />
<Entry Text="{Binding SearchQuery, Mode=OneWayToSource}" />

<!-- ❌ Redundant β€” just noise -->
<Label Text="{Binding Score, Mode=OneWay}" />
<Entry Text="{Binding UserName, Mode=TwoWay}" />

Compiled bindings β€” x:DataType placement rules

Compiled bindings are 8–20Γ— faster than reflection-based bindings. Enable with x:DataType.

Place x:DataType only where BindingContext is set:

  1. Page root β€” where you assign BindingContext.
  2. DataTemplate β€” which creates a new binding scope.

Do not scatter x:DataType on child elements. Adding x:DataType="x:Object" on children to "escape" compiled bindings is an anti-pattern β€” it disables compile-time checking and reintroduces reflection. To opt out for a single binding, use x:DataType="{x:Null}" on that element (see also: maui-xaml-authoring skill).

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

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

DataTemplate always needs its own x:DataType:

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

Treat compiler warnings as errors in CI

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)
<WarningsAsErrors>XC0022;XC0025</WarningsAsErrors>

.NET 9+ compiled code bindings

Fully AOT-safe, no reflection:

label.SetBinding(Label.TextProperty,
    static (PersonViewModel vm) => vm.FullName);

entry.SetBinding(Entry.TextProperty,
    static (PersonViewModel vm) => vm.Age,
    mode: BindingMode.TwoWay,
    converter: new IntToStringConverter());

Threading caveat

MAUI automatically marshals PropertyChanged to the UI thread β€” you can raise it from any thread. However, direct ObservableCollection mutations (Add/Remove) from background threads may still crash:

// βœ… Safe for PropertyChanged
await Task.Run(() => Items = LoadData());

// ⚠️ ObservableCollection.Add β€” dispatch to UI thread
MainThread.BeginInvokeOnMainThread(() => Items.Add(newItem));

Performance tips

  • Compiled bindings eliminate reflection β€” always prefer them.
  • NativeAOT / trimming: Reflection-based bindings break under trimming. Compiled bindings (XAML x:DataType or code SetBinding with lambdas) are trimmer- and AOT-safe.
  • Use OneTime mode for truly static data to skip change-tracking registration.
  • Avoid complex converter chains in hot paths β€” pre-compute values in the ViewModel instead.

Source: SKILL.md on GitHub

1 warning15d4 checks Β· Risk SAFE
  • Gen Agent Trust Hub15d

    The skill provides standard documentation and technical guidance for .NET MAUI data binding practices. No security issues, malicious patterns, or suspicious activities were detected.

  • Socket15d

    No alerts

  • Snyk15d

    Risk: LOW Β· No issues

  • Runlayer7mo

    1/1 file flagged

Signed by skilld at 2fa0067. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 6 months ago

README badge

README badge for davidortinau/maui-skills/maui-data-binding