dotnet/maui · error · BuildException
XC0020
XC0020
Error message
The name of the BindableProperty {0} does not end with "Property". What it means
XAML compiler (XamlC) validation, error XC0020. Every Maui BindableProperty field must follow the naming convention <Name>Property. GetBindablePropertyType checks the referenced field name ends with 'Property' and throws XC0020 if it does not, because the suffix is how XamlC derives the CLR property name to read the property's type.
Source
Thrown at src/Controls/src/Build.Tasks/BindablePropertyReferenceExtensions.cs:14
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using Mono.Cecil;
namespace Microsoft.Maui.Controls.Build.Tasks
{
static class BindablePropertyReferenceExtensions
{
public static TypeReference GetBindablePropertyType(this FieldReference bpRef, XamlCache cache, IXmlLineInfo iXmlLineInfo, ModuleDefinition module)
{
if (!bpRef.Name.EndsWith("Property", StringComparison.InvariantCulture))
throw new BuildException(BuildExceptionCode.BPName, iXmlLineInfo, null, bpRef.Name);
var bpName = bpRef.Name.Substring(0, bpRef.Name.Length - 8);
var owner = bpRef.DeclaringType;
var getter = owner.GetProperty(cache, pd => pd.Name == bpName, out TypeReference declaringTypeRef)?.GetMethod;
if (getter == null || getter.IsStatic || !getter.IsPublic)
getter = null;
getter = getter ?? owner.GetMethods(cache, md => md.Name == $"Get{bpName}" &&
md.IsStatic &&
md.IsPublic &&
md.Parameters.Count == 1 &&
md.Parameters[0].ParameterType.InheritsFromOrImplements(cache, module.ImportReference(cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject"))), module).FirstOrDefault()?.Item1;
if (getter == null)
throw new BuildException(BuildExceptionCode.BPName, iXmlLineInfo, null, bpName, bpRef.DeclaringType);
return getter.ResolveGenericReturnType(declaringTypeRef, module);
}
public static TypeReference GetBindablePropertyTypeConverter(this FieldReference bpRef, XamlCache cache, ModuleDefinition module)View on GitHub (pinned to f377ff1c5e)
Solutions
- Use the BindableProperty field name with the 'Property' suffix (e.g. SpacingProperty, not Spacing).
- Verify the field is actually a public static BindableProperty on the referenced type.
- Double-check spelling against the type's documented BindableProperty fields.
Example fix
<!-- before --> <Setter Property="Spacing" Value="10" /> <!-- after --> <Setter Property="SpacingProperty" Value="10" />
Defensive patterns
Strategy: validation
Prevention
- Always reference BindableProperty fields by their full '<Name>Property' name in XAML.
- When authoring BindableProperties, follow the <Name>Property naming convention exactly.
- Let an IDE/snippet template generate the field + wrapper to avoid suffix typos.
When it happens
Trigger: XAML sets an attribute (typically a Setter.Property or an attached-property usage) to a static field whose name does not end with 'Property' — e.g. using the CLR property name 'Spacing' where the 'SpacingProperty' field is required, or pointing at a non-BindableProperty static field.
Common situations: Typing the CLR wrapper name instead of the field; referencing a plain static field that is not a BindableProperty; copy-paste typos in property names.
Related errors
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/6223710f3873cc1a.
Report an issue: GitHub.