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

Attached Properties

Learn how attached properties let one class define a property that can be set on any DependencyObject, powering layout systems like Grid.Row and Canvas.Left.

Data BindingIntermediate9 min readJul 10, 2026
Analogies

A Property Defined by One Type, Set on Another

Grid.Row is the canonical example: Grid defines the property, but it is set on children like a TextBlock or Button that are not Grid instances themselves and know nothing about Grid internally. This works because Grid.Row is a special kind of dependency property — an attached property — registered with DependencyProperty.RegisterAttached, exposing static GetRow/SetRow accessor methods instead of an instance CLR wrapper, so any DependencyObject can carry the value even though the defining type never touches that object's class hierarchy.

🏏

Cricket analogy: It is like a stadium assigning a specific seat number to a ticket holder — the stadium (Grid) defines the seating system, but the seat number is attached to any spectator's ticket (any DependencyObject) regardless of which team they support.

Registering and Using an Attached Property

csharp
public static class WatermarkService
{
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.RegisterAttached(
            "Text",
            typeof(string),
            typeof(WatermarkService),
            new FrameworkPropertyMetadata(string.Empty, OnTextChanged));

    public static string GetText(DependencyObject obj) =>
        (string)obj.GetValue(TextProperty);

    public static void SetText(DependencyObject obj, string value) =>
        obj.SetValue(TextProperty, value);

    private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is TextBox tb)
            AdornerLayer.GetAdornerLayer(tb)?.Add(new WatermarkAdorner(tb, (string)e.NewValue));
    }
}

// XAML usage on any TextBox, without WatermarkService in its inheritance chain:
// <TextBox local:WatermarkService.Text="Search..."/>

The static GetText/SetText method pair (matching the naming convention Get{Name}/Set{Name}) is what the XAML parser looks for when it encounters the attached property syntax owner.Property="value" on any element; without both methods present and correctly named, the property cannot be set from XAML even though the DependencyProperty itself is fully registered. Because SetValue works on any DependencyObject, attached properties are frequently used to add cross-cutting, reusable behavior (like the watermark above, or drag-and-drop helpers) to controls without subclassing them.

🏏

Cricket analogy: It is like a broadcaster's graphics package requiring both a 'tag player' and 'untag player' function pair before commentators can attach a live stat overlay to any player on screen — both halves must exist for the workflow to function.

Attached Properties vs. Regular Dependency Properties

A regular dependency property is registered with Register and is meaningful only in the context of instances of its owner type — Button.IsPressed only makes sense on a Button. An attached property is registered with RegisterAttached specifically because it is meant to be meaningful on arbitrary DependencyObject instances that have no relationship to the defining type; both still ultimately participate in the same GetValue/SetValue store and value-precedence system, so attached properties can be bound, styled, animated, and triggered exactly like regular dependency properties once set.

🏏

Cricket analogy: It is like the difference between a player's own batting average (meaningful only for that player) and a ground's altitude-adjustment tag (meaningful when attached to any match played there, regardless of team) — both are tracked in the same statistics database though.

Because attached properties can be set on any DependencyObject, it is easy to set one on a type where the owning class's change-handling logic does nothing meaningful — for example setting Grid.Row on an element that isn't a direct child of a Grid has no visible effect and produces no error. Always verify the attached property is set on an element whose parent actually reads it during layout.

  • Attached properties are registered with DependencyProperty.RegisterAttached and can be set on any DependencyObject, not just instances of the defining type.
  • The XAML parser requires matching static Get{Name}/Set{Name} accessor methods, not an instance CLR wrapper, to read and write the value.
  • Grid.Row, Canvas.Left, and DockPanel.Dock are classic examples used by layout panels to position arbitrary child elements.
  • Attached properties are commonly used to add reusable, cross-cutting behavior to existing controls without subclassing them.
  • They participate in the same GetValue/SetValue store and value-precedence chain as regular dependency properties, so they support binding, styling, and animation.
  • Setting an attached property on an element whose ancestor doesn't read it (e.g. Grid.Row outside a Grid) has no effect and raises no error.
  • PropertyChangedCallback on an attached property is where reusable behavior logic typically lives, since there is no owning instance to react in its own code-behind.

Practice what you learned

Was this page helpful?

Topics covered

#NET#WPFWindowsPresentationFoundationStudyNotes#MicrosoftTechnologies#AttachedProperties#Attached#Properties#Property#Defined#StudyNotes#SkillVeris