Open sandboxFocusImprove this doc

XAM052: Invalid Target of the AttachedProperty Aspect

Severity Error
Reported by PostSharp.Patterns.Xaml
Message [AttachedProperty] cannot be applied to <Target>: the target must be a static property of type Attached<T> with a public getter.

Cause

An attached property is declared by one class and set on objects of other classes, as Grid.Column is set on the children of a Grid. The AttachedPropertyAttribute aspect registers the attached property and assigns its target property an Attached<T> object, which reads and writes the value on any DependencyObject. The target must therefore be a static property of type Attached<T>, and its getter must be public.

PostSharp reports XAM052 when the AttachedPropertyAttribute aspect is applied to:

  • an instance property;
  • a property whose getter is not public;
  • a property of another type than Attached<T>, typically the type of the value itself;
  • a field, which C# allows because the aspect is a location-level aspect.

In the following example, the Column attached property is of type int instead of Attached<int>.

using System;
using System.Windows;
using PostSharp.Patterns.Xaml;

namespace Errors.XAM052_Error;

public class CardLayout : DependencyObject
{
    // An attached property must be of type Attached<T>, not of the type of its value.
    [AttachedProperty]
    public static int Column { get; private set; }
}

public class ContactCard : DependencyObject
{
}

public static class Program
{
    public static void Main()
    {
        Console.WriteLine( $"Column: {CardLayout.Column}" );
    }
}
error XAM052: XAM052_Error.cs(11,23): [AttachedProperty] cannot be applied to Errors.XAM052_Error.CardLayout.Column: the target must be a static property of type Attached<T> with a public getter.

Resolution

Declare the target as public static Attached<T> Name { get; private set; }, where T is the type of the value. Read and write the value on a given object with the GetValue(DependencyObject) and SetValue(DependencyObject, T) methods, and add a static SetName method that calls SetValue(DependencyObject, T), which the XAML compiler requires to set the property in XAML.

If you want a property that stores a value in each instance of its own class, use the DependencyPropertyAttribute aspect on an instance property instead.

In the following example, Column is of type Attached<int>, and the program sets it on a ContactCard.

using System;
using System.Windows;
using PostSharp.Patterns.Xaml;

namespace Errors.XAM052_Fixed;

// The [AttachedProperty] aspect initializes the property.
#pragma warning disable CS8618

public class CardLayout : DependencyObject
{
    // The property is of type Attached<int>, which reads and writes the value on any DependencyObject.
    [AttachedProperty]
    public static Attached<int> Column { get; private set; }

    public static void SetColumn( DependencyObject host, int value ) => Column.SetValue( host, value );
}

public class ContactCard : DependencyObject
{
}

public static class Program
{
    public static void Main()
    {
        var card = new ContactCard();
        CardLayout.SetColumn( card, 2 );
        Console.WriteLine( $"Column: {CardLayout.Column.GetValue( card )}" );
    }
}
Column: 2

See Also

Reference

AttachedPropertyAttribute
Attached<T>
DependencyPropertyAttribute

Other Resources

Attached Property
Dependency Property