100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
.NET

Markup Extensions Overview

How XAML's curly-brace syntax defers value creation to parse time through classes that implement MarkupExtension.

Markup ExtensionsIntermediate8 min readJul 10, 2026
Analogies

What Are Markup Extensions

A markup extension is a XAML construct that lets an attribute value be computed at parse time rather than written as a literal string. Any class that derives from System.Windows.Markup.MarkupExtension and overrides ProvideValue can be invoked from XAML using curly-brace syntax, such as {Binding Path=Name} or {StaticResource AppBrush}, and the XAML parser calls ProvideValue to obtain the actual object that gets assigned to the property.

🏏

Cricket analogy: Think of a markup extension like a night-watchman batter sent in for the last over: the scorecard slot (the attribute) is fixed, but who actually fills it is decided at the last moment by the team management, just as ProvideValue decides the real value only when the parser reaches that line.

Curly-Brace Syntax and How the Parser Resolves It

The curly-brace syntax {ExtensionName Arg1, Property2=Value2} is parsed by the XamlReader into a call against the corresponding MarkupExtension subclass. Positional arguments map to constructor parameters in declaration order, while Name=Value pairs map to public settable properties on the extension instance. Extensions can be nested, for example {Binding Converter={StaticResource BoolToVisibilityConverter}}, where the inner extension is fully resolved before being passed as a property value to the outer one.

🏏

Cricket analogy: It is like reading a cricket team's playing XI where the first names are locked batting order (positional) but roles like 'wicketkeeper' or 'vice-captain' are assigned by name afterward, just as positional and named markup-extension arguments are resolved differently by the parser.

Built-in and Custom Markup Extensions

The XAML and WPF/UWP frameworks ship several built-in extensions including {Binding}, {StaticResource}, {DynamicResource}, {x:Static}, {x:Type}, {x:Null}, and {x:Array}. Beyond these, developers can author custom extensions by subclassing MarkupExtension and implementing ProvideValue(IServiceProvider serviceProvider); the IServiceProvider parameter exposes services such as IProvideValueTarget, which reveals the target object and property the extension is being applied to, enabling context-aware value production.

🏏

Cricket analogy: It is like a franchise's core squad of specialist players (built-in extensions) supplemented by a locally scouted talent (custom extension) who still has to prove themselves against the same selection criteria, just as a custom MarkupExtension must still honor the ProvideValue contract.

csharp
public class UppercaseExtension : MarkupExtension
{
    public string Text { get; set; }

    public UppercaseExtension() { }

    public UppercaseExtension(string text)
    {
        Text = text;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return Text?.ToUpperInvariant() ?? string.Empty;
    }
}

<!-- Usage in XAML -->
<TextBlock Text="{local:Uppercase 'hello world'}" />

By convention, a custom markup extension class name ends in 'Extension', but XAML lets you drop that suffix when using the curly-brace syntax, so UppercaseExtension can be invoked simply as {local:Uppercase ...}.

  • Markup extensions defer value creation to parse time via a ProvideValue method.
  • Curly-brace syntax {Name Arg} maps positional arguments to constructor parameters and Name=Value pairs to properties.
  • Extensions can be nested, with inner extensions resolving before outer ones consume their result.
  • Built-in extensions include Binding, StaticResource, DynamicResource, x:Static, x:Type, x:Null, and x:Array.
  • Custom extensions subclass MarkupExtension and override ProvideValue(IServiceProvider).
  • IServiceProvider exposes IProvideValueTarget so a custom extension can inspect the target object/property.
  • The 'Extension' suffix on a class name can be omitted when invoking it from XAML.

Practice what you learned

Was this page helpful?

Topics covered

#NET#XAMLStudyNotes#MicrosoftTechnologies#MarkupExtensionsOverview#Markup#Extensions#Curly#Brace#StudyNotes#SkillVeris