Reuse effects in .NET MAUI

While there are many benefits to using .NET Multi-platform App UI (.NET MAUI) handlers to customize controls, it's still possible to use Xamarin.Forms effects in .NET MAUI apps. For more information about effects, see Xamarin.Forms effects.

The process for migrating a Xamarin.Forms effect to .NET MAUI is to:

  1. Remove the effect attributes from your effect classes. For more information, see Remove effect attributes.
  2. Remove the effect using directives. For more information, see Remove using directives.
  3. Add the effect code into the appropriate location in your .NET MAUI app project. For more information, see Add the effect code.
  4. Register the effect. For more information, see Register the effect.
  5. Consume your .NET MAUI effect. For more information, see Consume the effect.

Remove effect attributes

Any ResolutionGroupNameAttribute and ExportEffectAttribute attributes should be removed from your effect classes.

Remove using directives

Any references to the Xamarin.Forms and Xamarin.Forms.Platform.* namespaces should be removed from your effect classes.

Add the effect code

If you're using a .NET MAUI multi-targeted project, your effect code should be combined into a single file and placed outside the Platforms folder. This requires you to combine your RoutingEffect implementation and PlatformEffect implementations into a single file, using conditional compilation around platform code. However, if your solution has separate projects per-platform, then you should move the platform-specific effect files into the corresponding projects.

In .NET MAUI, the RoutingEffect class is in the Microsoft.Maui.Controls namespace. This namespace is one of .NET MAUI's implicit global using directives, and so you don't need to add a using directive for it. However, the PlatformEffect class is in the Microsoft.Maui.Controls.Platform namespace, for which you must add a using directive.

The following code example shows a FocusRoutingEffect class and its platform implementations combined into a single file:

using Microsoft.Maui.Controls.Platform;

namespace MyMauiApp.Effects;

internal class FocusRoutingEffect : RoutingEffect
{
}

#if ANDROID
internal class FocusPlatformEffect : PlatformEffect
{
    protected override void OnAttached()
    {
        // Customize the control here
    }

    protected override void OnDetached()
    {
        // Cleanup the control customization here
    }
}
#elif IOS
internal class FocusPlatformEffect : PlatformEffect
{
    protected override void OnAttached()
    {
        // Customize the control here
    }

    protected override void OnDetached()
    {
        // Cleanup the control customization here
    }
}
#elif WINDOWS
internal class FocusPlatformEffect : PlatformEffect
{
    protected override void OnAttached()
    {
        // Customize the control here
    }

    protected override void OnDetached()
    {
        // Cleanup the control customization here
    }
}
#endif

Register the effect

In your .NET MAUI app project, open MauiProgram.cs and call the ConfigureEffects method on the MauiAppBuilder object in the CreateMauiApp method:

public static MauiApp CreateMauiApp()
{
  var builder = MauiApp.CreateBuilder();
  builder
    .UseMauiApp<App>()
    .ConfigureEffects(effects =>
    {
      effects.Add<FocusRoutingEffect, FocusPlatformEffect>();
    });

  return builder.Build();
}

The effect is registered with the ConfigureEffects method, whose configureDelegate registers the PlatformEffect implementation against its RoutingEffect implementation.

Consume the effect

The effect can be consumed in a .NET MAUI app by adding it to the Effects collection of a control:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MyMauiApp.Effects"
             x:Class="MyMauiApp.MainPage">
    <VerticalStackLayout>
        <Entry Text="Enter your text">
            <Entry.Effects>
                <local:FocusRoutingEffect />
            </Entry.Effects>
        </Entry>
    </VerticalStackLayout>
</ContentPage>