MAUI Creating Custom Attached Properties


Custom attached properties are a powerful way to extend existing controls with new properties not part of the control basic definition in .NET MAUI. It also gives you the ability to create your reusable behaviors or styles that you can add to multiple different elements in your app.

Attached Properties Overview

  • Special type of property that can be set on an element which otherwise lacks that property.
  • Purpose: Styling, behaviors, and reusability of the control across multiple control types are achieved by not modifying the control itself, but by adding extra information to a control.

Adding a Custom BorderColor Attached Property

In this example we will create a custom attached property, BorderColor, we can use to add a border to controls like Label, Entry, Textbox etc..

Let’s start;

Create an Attached Property: Put the attached property into a new static class named BorderEffect.

BorderEffect.cs

using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;

namespace MauiAppExample
{
    public static class BorderEffect
    {
        // Define the attached property
        public static readonly BindableProperty BorderColorProperty =
            BindableProperty.CreateAttached(
                propertyName: "BorderColor",
                returnType: typeof(Color),
                declaringType: typeof(BorderEffect),
                defaultValue: Colors.Transparent,
                propertyChanged: OnBorderColorChanged);

        // Getter method to retrieve the value of the attached property
        public static Color GetBorderColor(BindableObject view)
        {
            return (Color)view.GetValue(BorderColorProperty);
        }

        // Setter method to set the value of the attached property
        public static void SetBorderColor(BindableObject view, Color value)
        {
            view.SetValue(BorderColorProperty, value);
        }

        // Callback when the attached property changes
        private static void OnBorderColorChanged(BindableObject bindable, object oldValue, object newValue)
        {
            if (bindable is VisualElement visualElement)
            {
                if (newValue is Color newColor)
                {
                    // Apply the border color effect to the visual element
                    visualElement.Background = newColor.WithAlpha(0.2f); // Just as an example effect
                }
            }
        }
    }
}

Let me explain the code above;

Define Attached Property (BorderColorProperty):

  • Uses BindableProperty.CreateAttached to create.
  • propertyName: The name of the attached property, BorderColor.
  • returnType: It knows the type of the property (Pursuant to the Color.).
  • declaringType: The class that defines the property (BorderEffect).
  • defaultValue: The default value is set to Colors.Transparent.
  • propertyChanged: Invoked by the property when it changes: OnBorderColorChanged

Getter and Setter:

  • GetBorderColor: Its value of BorderColor is retrieved.
  • SetBorderColor: It sets value of BorderColor.

Property Changed Callback (OnBorderColorChanged):

  • We can change the properties (background, etc.) of the VisualElement then, when the BorderColor changes.

Using Attached Property in XAML

Now I am able to use the custom attached property in XAML to add borders to different controls.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MauiAppExample"
             x:Class="MauiAppExample.MainPage">

    <StackLayout Padding="20" Spacing="20" VerticalOptions="Center">

        <Label Text="Hello, World!"
               FontSize="Large"
               HorizontalOptions="Center"
               VerticalOptions="Center"
               local:BorderEffect.BorderColor="Red" />

        <Entry Placeholder="Enter some text"
               HorizontalOptions="FillAndExpand"
               local:BorderEffect.BorderColor="Green" />

        <Button Text="Click Me"
                local:BorderEffect.BorderColor="Blue"
                HorizontalOptions="Center" />
    </StackLayout>
</ContentPage>

xmlns:local="clr-namespace:MauiAppExample": This namespace reference local=”clr-namespace:MauiAppExample” lets us use BorderEffect in XAML.

Applying BorderEffect.BorderColor:

  • And the BorderColor attached property is used for border color effect applied to different controls (Label, Entry, and Button).
  • Here, the effect is defined in the OnBorderColorChanged call back of code behind.

Customization of the Visual Representation

You can change the visual representation of the element in the OnBorderColorChanged method. For instance, you could provide border with a given thickness. However, since .NET MAUI doesn’t provide direct access to border thickness for all the controls you may need to use platform specific renderers or effects for more complex customization.

Here is how to adjust the visual element’s background to give the appearance of a border:

OnBorderColorChanged Updated Example:

private static void OnBorderColorChanged(BindableObject bindable, object oldValue, object newValue)
{
    if (bindable is VisualElement visualElement)
    {
        if (newValue is Color newColor)
        {
            // This simple example changes the background color to indicate a border effect.
            // You can implement a custom effect renderer for more detailed visual changes.
            visualElement.Background = newColor.WithAlpha(0.2f);
        }
    }
}

Summary of Creating Custom Attached Properties

StepDescription
Define Attached PropertyCreate the property using BindableProperty.CreateAttached().
Getter and SetterProvide Get and Set methods to access the property value.
Property Changed CallbackHandle property changes to apply the effect (e.g., changing the visual state).
Use in XAMLApply the attached property to various controls in XAML.

Attached Properties in Real World use cases.

  • Styling Multiple Controls:
    • Don’t have to modify each individual control to apply consistent styles (e.g., borders, padding, margins) to controls.
  • Adding Behavior:
    • Behaviors such as tap gesture recognizers or hover effects to multiple controls.
  • Reusable Utilities:
    • Add custom commands or properties that affect layout behavior, but also create properties that can be attached to a lot of different elements, making utility style additions.