maui-accessibility
Guide for making .NET MAUI apps accessible — screen reader support via SemanticProperties, heading levels, AutomationProperties…
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",
$ npx -y skills add davidortinau/maui-skills --skill maui-data-binding --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/maui-data-bindingContext preview
The summary Claude sees to decide when to auto-load this skill.
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",
name: maui-data-binding description: >- 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).
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 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>| 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>
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());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));
A collection of 41 skills for .NET MAUI development, UI/UX design reasoning, and Xamarin migration, designed for use with GitHub Copilot CLI and Claude Code.
Guide for making .NET MAUI apps accessible — screen reader support via SemanticProperties, heading levels, AutomationProperties…
.NET MAUI view animations, custom animations, easing functions, rotation, scale, translation, and fade effects. USE FOR: "animate…
.NET MAUI app icon configuration, splash screen setup, SVG to PNG conversion at build time, composed/adaptive icons, and…
.NET MAUI app lifecycle guidance covering the four app states (not running, running, deactivated, stopped), cross-platform Window…
Guide for .NET MAUI apps consuming .NET Aspire-hosted backend services. Covers AppHost configuration, service discovery for…
Add authentication to .NET MAUI apps. Covers WebAuthenticator for generic OAuth 2.0 / social login, and MSAL.NET for Microsoft…