Attached properties

.NET Multi-platform App UI (.NET MAUI) attached properties enable an object to assign a value for a property that its own class doesn't define. For example, child elements can use attached properties to inform their parent element of how they are to be presented in the user interface. The Grid layout enables the row and column of a child to be specified by setting the Grid.Row and Grid.Column attached properties. Grid.Row and Grid.Column are attached properties because they are set on elements that are children of a Grid, rather than on the Grid itself.

Bindable properties should be implemented as attached properties in the following scenarios:

  • When there's a need to have a property setting mechanism available for classes other than the defining class.
  • When the class represents a service that needs to be easily integrated with other classes.

For more information about bindable properties, see Bindable properties.

Create an attached property

The process for creating an attached property is as follows:

  1. Create a BindableProperty instance with one of the CreateAttached method overloads.
  2. Provide static GetPropertyName and SetPropertyName methods as accessors for the attached property.

Create a property

When creating an attached property for use on other types, the class where the property is created does not have to derive from BindableObject. However, the target property for accessors should be of, or derive from, BindableObject. For more information about target properties, see Basic bindings.

An attached property can be created by declaring a public static readonly property of type BindableProperty. The bindable property should be set to the returned value of one of the BindableProperty.CreateAttached method overloads. The declaration should be within the body of the owning class, but outside of any member definitions.

Important

The naming convention for attached properties is that the attached property identifier must match the property name specified in the CreateAttached method, with "Property" appended to it.

The following code shows an example of an attached property:

public class MyControl
{
    public static readonly BindableProperty HasShadowProperty =
        BindableProperty.CreateAttached("HasShadow", typeof(bool), typeof(MyControl), false);
}

This creates an attached property named HasShadowProperty, of type bool. The property is owned by the MyControl class, and has a default value of false. Ownership, in this case, means that the property will be accessed in XAML using the format Type.Property, for example MyControl.HasShadow.

For more information about creating bindable properties, including parameters that can be specified during creation, see Create a bindable property.

Create accessors

Static GetPropertyName and SetPropertyName methods are required as accessors for the attached property, otherwise the property system will be unable to use the attached property. The GetPropertyName accessor should conform to the following signature:

public static valueType GetPropertyName(BindableObject target)

The GetPropertyName accessor should return the value that's contained in the corresponding BindableProperty field for the attached property. This can be achieved by calling the GetValue method, passing in the bindable property identifier on which to get the value, and then casting the resulting value to the required type.

The SetPropertyName accessor should conform to the following signature:

public static void SetPropertyName(BindableObject target, valueType value)

The SetPropertyName accessor should set the value of the corresponding BindableProperty field for the attached property. This can be achieved by calling the SetValue method, passing in the bindable property identifier on which to set the value, and the value to set.

For both accessors, the target object should be of, or derive from, BindableObject. For more information about target objects, see Basic bindings.

The following code example shows accessors for the HasShadow attached property:

public class MyControl
{
    public static bool GetHasShadow(BindableObject view)
    {
        return (bool)view.GetValue (HasShadowProperty);
    }

    public static void SetHasShadow(BindableObject view, bool value)
    {
        view.SetValue(HasShadowProperty, value);
    }  
}

Consume an attached property

Once an attached property has been created, it can be consumed from XAML or code. In XAML, this is achieved by declaring a namespace with a prefix, with the namespace declaration indicating the Common Language Runtime (CLR) namespace name, and optionally an assembly name. For more information, see XAML Namespaces.

The following example demonstrates a XAML namespace for a custom type that contains an attached property, which is defined within the same assembly as the app code that's referencing the custom type:

<ContentPage ... xmlns:local="clr-namespace:ShadowDemo" ...>
  ...
</ContentPage>

The namespace declaration is then used when setting the attached property on a specific control, as demonstrated in the following XAML:

<Label Text="Label with shadow" local:MyControl.HasShadow="true" />

The equivalent C# code is shown in the following code example:

Label label = new Label { Text = "Label with shadow" };
MyControl.SetHasShadow (label, true);

Consume an attached property with a style

Attached properties can also be added to a control by a style. The following XAML code example shows an explicit style for Label controls that uses the HasShadow attached property:

<Style x:Key="ShadowStyle" TargetType="Label">
  <Style.Setters>
    <Setter Property="local:MyControl.HasShadow" Value="true" />
  </Style.Setters>
</Style>

The Style can be applied to a Label by setting its Style property to the Style instance using the StaticResource markup extension, as demonstrated in the following code example:

<Label Text="Label with shadow" Style="{StaticResource ShadowStyle}" />

For more information about styles, see Styles.

Advanced scenarios

When creating an attached property, there are some optional parameters that can be set to enable advanced attached property scenarios. This includes detecting property changes, validating property values, and coercing property values. For more information, see Advanced scenarios.