/maui-data-binding
Guidance for .NET MAUI XAML and C# data bindings — compiled bindings, INotifyPropertyChanged / ObservableObject, value converters, binding modes, multi-binding, relative bindings, fallbacks, and MVVM best practices. USE FOR: setting up compiled bindings with x:DataType,
$ npx -y skills add dotnet/skills --skill maui-data-binding --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/maui-data-binding
Context preview
The summary Claude sees to decide when to auto-load this skill.
Guidance for .NET MAUI XAML and C# data bindings — compiled bindings, INotifyPropertyChanged / ObservableObject, value converters, binding modes, multi-binding, relative bindings, fallbacks, and MVVM best practices. USE FOR: setting up compiled bindings with x:DataType,
SKILL.md
maui-data-binding.SKILL.mdname: maui-data-binding
description: >-
Guidance for .NET MAUI XAML and C# data bindings — compiled bindings,
INotifyPropertyChanged / ObservableObject, value converters, binding modes,
multi-binding, relative bindings, fallbacks, and MVVM best practices.
USE FOR: setting up compiled bindings with x:DataType, implementing
INotifyPropertyChanged or CommunityToolkit ObservableObject, creating
IValueConverter / IMultiValueConverter, choosing binding modes, configuring
BindingContext, relative bindings, binding fallbacks, StringFormat,
code-behind SetBinding with lambdas, and enforcing XC0022/XC0025 warnings.
DO NOT USE FOR: CollectionView item templates and layouts (use
maui-collectionview), Shell navigation data passing (use
maui-shell-navigation), dependency injection (use maui-dependency-injection),
or animations triggered by property changes (use .NET MAUI animation APIs).
license: MIT
.NET MAUI Data Binding
Wire UI controls to ViewModel properties with compile-time safety, correct change notification, and minimal overhead. Prefer compiled bindings everywhere and treat binding warnings as build errors.
When to Use
- Adding `x:DataType` compiled bindings to a new or existing page
- Implementing `INotifyPropertyChanged` or CommunityToolkit `ObservableObject`
- Creating or consuming `IValueConverter` / `IMultiValueConverter`
- Choosing the correct `BindingMode` for a control property
- Setting `BindingContext` in XAML or code-behind
- Using relative bindings (`Self`, `AncestorType`, `TemplatedParent`)
- Applying `StringFormat`, `FallbackValue`, or `TargetNullValue`
- Writing AOT-safe code bindings with `SetBinding` and lambdas (.NET 9+)
When Not to Use
- **CollectionView layouts / templates** — use the `maui-collectionview` skill
- **Shell navigation parameters** — use the `maui-shell-navigation` skill
- **Service registration / DI** — use the `maui-dependency-injection` skill
- **Property-change-triggered animations** — use built-in [.NET MAUI animation APIs](https://learn.microsoft.com/dotnet/maui/user-interface/animation/basic)
Inputs
- A .NET MAUI project targeting .NET 8 or later
- XAML pages or C# code-behind where bindings are declared
- A ViewModel class (or plan to create one)
Rules That Change the Answer
Apply these to every binding answer — they are the differences between "it compiles" and "it actually updates the UI".
| Situation | Do this | Not this | |---|---|---| | Deciding where `x:DataType` goes | Put it wherever a binding scope starts — the page/view root, and **each** `DataTemplate` | Scattering it on arbitrary children that share the parent's `BindingContext` | | A binding falls back to reflection (XC0022 / XC0023) | Add the right `x:DataType` for that binding scope; for XC0023 remove the explicit `x:DataType="{x:Null}"` | `x:DataType="x:Object"` to silence it — this disables compile-time checking | | A `DataTemplate` inherits `x:DataType` from an outer scope (XC0024) | Give the `DataTemplate` its **own** `x:DataType` | Leaving it to resolve against the wrong type | | ViewModel change notification | `ObservableObject` + `[ObservableProperty]`, or implement `INotifyPropertyChanged` | A plain POCO base class — bindings will never update | | Bindings show blank | Check `BindingContext` is actually set | Assuming the binding path is wrong | | Enforcing compiled bindings | Set `MauiEnableXamlCBindingWithSourceCompilation` to `true`, **then** `<WarningsAsErrors>XC0022;XC0025</WarningsAsErrors>` | Promoting `XC0025` without the switch if the project uses `Source=` / `RelativeSource` bindings |
**Do not** restructure a ViewModel or add a converter that the user did not ask for and that fixes no real defect. Adding `x:DataType` is different: when you are already editing a page's bindings, recommending compiled bindings is in scope.
---
Compiled Bindings — x:DataType Placement
Compiled bindings are **8–20× faster** than reflection-based bindings and are required for NativeAOT / trimming. Enable them with `x:DataType`.
Placement rules
Set `x:DataType` **only where `BindingContext` is set**:
1. **Page / View root** — where you assign `BindingContext`. 2. **DataTemplate** — which creates a new binding scope.
Do **not** scatter `x:DataType` on arbitrary 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.
<!-- ✅ Correct: x:DataType at the page root -->
<ContentPage xmlns:vm="clr-namespace:MyApp.ViewModels"
x:DataType="vm:MainViewModel">
<StackLayout>
<Label Text="{Binding Title}" />
<Slider Value="{Binding Progress}" />
</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}" />
</StackLayout>
</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>Enforce binding warnings as errors
| Warning | Meaning | |---------|---------| | **XC0022** | Binding used **without `x:DataType` in scope** — not compiled, falls back to reflection | | **XC0023** | Binding not compiled because `x:DataType` is **explicitly `null`** | | **XC0024** | `x:DataType` came from an **outer scope** — annotate the `DataTemplate` with its own `x:DataType` | | **XC0025** | Binding not compiled because it has an explicit **`Source`** — enable `<MauiEnableXamlCBindingWithSourceCompilation>` |
> These four codes are **verified against .NET 10 / .NET 11 MAUI** > (`Build.Tasks/BuildException.cs`, `ErrorMessages.resx
Read more
name: maui-data-binding description: >- Guidance for .NET MAUI XAML and C# data bindings — compiled bindings, INotifyPropertyChanged / ObservableObject, value converters, binding modes, multi-binding, relative bindings, fallbacks, and MVVM best practices. USE FOR: setting up compiled bindings with x:DataType, implementing INotifyPropertyChanged or CommunityToolkit ObservableObject, creating IValueConverter / IMultiValueConverter, choosing binding modes, configuring BindingContext, relative bindings, binding fallbacks, StringFormat, code-behind SetBinding with lambdas, and enforcing XC0022/XC0025 warnings. DO NOT USE FOR: CollectionView item templates and layouts (use maui-collectionview), Shell navigation data passing (use maui-shell-navigation), dependency injection (use maui-dependency-injection), or animations triggered by property changes (use .NET MAUI animation APIs). license: MIT
.NET MAUI Data Binding
Wire UI controls to ViewModel properties with compile-time safety, correct change notification, and minimal overhead. Prefer compiled bindings everywhere and treat binding warnings as build errors.
When to Use
- Adding `x:DataType` compiled bindings to a new or existing page
- Implementing `INotifyPropertyChanged` or CommunityToolkit `ObservableObject`
- Creating or consuming `IValueConverter` / `IMultiValueConverter`
- Choosing the correct `BindingMode` for a control property
- Setting `BindingContext` in XAML or code-behind
- Using relative bindings (`Self`, `AncestorType`, `TemplatedParent`)
- Applying `StringFormat`, `FallbackValue`, or `TargetNullValue`
- Writing AOT-safe code bindings with `SetBinding` and lambdas (.NET 9+)
When Not to Use
- **CollectionView layouts / templates** — use the `maui-collectionview` skill
- **Shell navigation parameters** — use the `maui-shell-navigation` skill
- **Service registration / DI** — use the `maui-dependency-injection` skill
- **Property-change-triggered animations** — use built-in [.NET MAUI animation APIs](https://learn.microsoft.com/dotnet/maui/user-interface/animation/basic)
Inputs
- A .NET MAUI project targeting .NET 8 or later
- XAML pages or C# code-behind where bindings are declared
- A ViewModel class (or plan to create one)
Rules That Change the Answer
Apply these to every binding answer — they are the differences between "it compiles" and "it actually updates the UI".
| Situation | Do this | Not this | |---|---|---| | Deciding where `x:DataType` goes | Put it wherever a binding scope starts — the page/view root, and **each** `DataTemplate` | Scattering it on arbitrary children that share the parent's `BindingContext` | | A binding falls back to reflection (XC0022 / XC0023) | Add the right `x:DataType` for that binding scope; for XC0023 remove the explicit `x:DataType="{x:Null}"` | `x:DataType="x:Object"` to silence it — this disables compile-time checking | | A `DataTemplate` inherits `x:DataType` from an outer scope (XC0024) | Give the `DataTemplate` its **own** `x:DataType` | Leaving it to resolve against the wrong type | | ViewModel change notification | `ObservableObject` + `[ObservableProperty]`, or implement `INotifyPropertyChanged` | A plain POCO base class — bindings will never update | | Bindings show blank | Check `BindingContext` is actually set | Assuming the binding path is wrong | | Enforcing compiled bindings | Set `MauiEnableXamlCBindingWithSourceCompilation` to `true`, **then** `<WarningsAsErrors>XC0022;XC0025</WarningsAsErrors>` | Promoting `XC0025` without the switch if the project uses `Source=` / `RelativeSource` bindings |
**Do not** restructure a ViewModel or add a converter that the user did not ask for and that fixes no real defect. Adding `x:DataType` is different: when you are already editing a page's bindings, recommending compiled bindings is in scope.
---
Compiled Bindings — x:DataType Placement
Compiled bindings are **8–20× faster** than reflection-based bindings and are required for NativeAOT / trimming. Enable them with `x:DataType`.
Placement rules
Set `x:DataType` **only where `BindingContext` is set**:
1. **Page / View root** — where you assign `BindingContext`. 2. **DataTemplate** — which creates a new binding scope.
Do **not** scatter `x:DataType` on arbitrary 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.
<!-- ✅ Correct: x:DataType at the page root -->
<ContentPage xmlns:vm="clr-namespace:MyApp.ViewModels"
x:DataType="vm:MainViewModel">
<StackLayout>
<Label Text="{Binding Title}" />
<Slider Value="{Binding Progress}" />
</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}" />
</StackLayout>
</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>Enforce binding warnings as errors
| Warning | Meaning | |---------|---------| | **XC0022** | Binding used **without `x:DataType` in scope** — not compiled, falls back to reflection | | **XC0023** | Binding not compiled because `x:DataType` is **explicitly `null`** | | **XC0024** | `x:DataType` came from an **outer scope** — annotate the `DataTemplate` with its own `x:DataType` | | **XC0025** | Binding not compiled because it has an explicit **`Source`** — enable `<MauiEnableXamlCBindingWithSourceCompilation>` |
> These four codes are **verified against .NET 10 / .NET 11 MAUI** > (`Build.Tasks/BuildException.cs`, `ErrorMessages.resx
This repository contains the .NET team's curated set of core skills and custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io. 📊 Dashboard - Accuracy and efficiency scoring trends for contained plugins (
Repo: dotnet/skills
Other skills on dotnet-skills.
- /csharp-scripts
Run file-based C# apps with the .NET CLI when the user explicitly wants C#/.NET code without creating a project. Use for C# language/API experiments, one-file C# apps, small multi-file C# apps composed with `#:include`/`#:exclude`, or C# file-based apps linked with `#:ref`. Do
Open skill - /dotnet-pinvoke
Correctly call native (C/C++) libraries from .NET using P/Invoke and LibraryImport. Covers function signatures, string marshalling, memory lifetime, SafeHandle, and cross-platform patterns. USE FOR: writing new P/Invoke or LibraryImport declarations, reviewing or debugging
Open skill - /nuget-trusted-publishing
Set up NuGet trusted publishing (OIDC) on a GitHub Actions repo — replaces long-lived API keys with short-lived tokens. USE FOR: trusted publishing, NuGet OIDC, keyless NuGet publish, migrate from NuGet API key, NuGet/login, secure NuGet publishing. DO NOT USE FOR: publishing to
Open skill - /technology-selection
Guides technology selection and implementation of AI and ML features in .NET 8+ applications using ML.NET, Microsoft.Extensions.AI (MEAI), Microsoft Agent Framework (MAF), GitHub Copilot SDK, ONNX Runtime, and OllamaSharp. Covers the full spectrum from classic ML through modern
Open skill - /configuring-opentelemetry-dotnet
Configure OpenTelemetry distributed tracing, metrics, and logging in ASP.NET Core using the .NET OpenTelemetry SDK. Use when adding observability, setting up OTLP exporters, creating custom metrics/spans, or troubleshooting distributed trace correlation.
Open skill - /convert-blazor-server-to-webapp
Guides conversion of a pre-.NET 8 Blazor Server app into a .NET 8+ Blazor Web App. USE FOR: migrating apps that use AddServerSideBlazor and MapBlazorHub to the AddRazorComponents/MapRazorComponents model, converting _Host.cshtml to an App.razor root component, replacing
Open skill

