Telerik blogs

Learn how to migrate renderers from Xamarin Forms to .NET MAUI handlers.

Among the most important points of the evolution of Xamarin.Forms to .NET MAUI are the improvements that have been applied based on the learning obtained.

I know that you have worked with custom renderers in Xamarin.Forms and you are probably wondering how you can use them in .NET MAUI. You are in the right place! In this article, we will learn how to migrate custom renderers from Xamarin Forms to .NET MAUI handlers.

Get To Know Handlers

.NET MAUI provides a graphical interface on which we can communicate with the user in a more effective way, displaying and sending data. Each of the controls that we use to build this interface has an interface representation that abstracts the control. The controls that implement this interface are known as native views, which are used on each platform.

Handlers are responsible for instantiating the underlying native view and mapping the cross-platform control API to the native view API. Next, you will see this explanation graphically:

Handlers structure cross-platform controls virtual view to handlers to native views

What Are Mappers?

Mappers are a key concept in .NET MAUI handlers, usually providing a property mapper and sometimes a command mapper, which maps the cross-platform control’s API to the native view’s API.

Let’s understand a little more:

  • A property mapper is a new concept introduced by handlers. This is a Dictionary responsible for deciding the actions to take when a property change occurs in the multiplatform control. Each platform handler provides implementations of actions that subsequently handle the native view API. That means that when you set a property on a cross-platform control, the underlying native view is updated as required.
  • A command mapper defines what actions to take when the cross-platform control sends commands (instructions) to native views. Unlike property mappers, they allow passing additional data.

The advantage of using mappers for updating native views is that they can be unbound from cross-platform controls. This eliminates the need for native views to subscribe and unsubscribe from cross-platform control events.

Evolving From Xamarin Renderers to .NET MAUI Handlers

Let’s highlight some of the most relevant improvements from the evolution of Xamarin renderers to .NET MAUI handlers:

Xamarin Renderers

  • Despite the improvements implemented, it is important to know that it’s still possible to use the custom renderer pattern for customization at the platform level familiar to Xamarin.Forms developers. You can take a look at the article “ Using Custom Renderers in .NET MAUI.”
  • In Xamarin Forms, each renderer has a reference to the cross-platform element. It generally depends on INotifyPropertyChanged for its operation. .NET MAUI uses a new pattern called a handler.

.NET MAUI Renderers

  • Among the main benefits of using handlers are improved performance and extensibility.
  • The new handler architecture in .NET MAUI reduces the number of UI controls required to render a view and decouples platform controls from the framework itself by removing view settings.
  • In .NET MAUI, handlers invert the relationship between the framework and the platform, so the platform control only needs to handle the needs of the framework. This makes it much easier to extend or override when needed.

Migration to a Handlers Class

For this migration, we will make an example for an EditText control in Android. We will be using an example obtained from the MAUI wiki on GitHub.

We will learn how to do it step by step:

1. Create an interface which implements Iview.

public interface ICustomEntry : IView
{
     public string Text { get; }
     public Color TextColor { get; }
}

2. Create a subclass of the ViewHandler class.

This class renders the platform control.

public partial class CustomEntryHandler : ViewHandler<ICustomEntry, EditText>
{

}

🗒 The ViewHandler class provides VirtualView properties that are used to access the cross-platform control from its controller and the PlatformView property that handles accessing the native view on each platform that implements the cross-platform control.

3. Override the CreatePlatformView method.

This method is contained in the ViewHandler subclass, which should create and return the native view that implements the cross-platform control. This method renders the platform control.

public partial class CustomEntryHandler : ViewHandler<ICustomEntry, EditText>
{ 
    protected override EditText CreatePlatformView()
    { 
	    return new EditText(Context);
    }
}

4. Create the PropertyMapper dictionary.

This is responsible for defining the action that will be taken when cross-platform property changes.

public partial class CustomEntryHandler : ViewHandler<ICustomEntry, EditText>
{
    public static PropertyMapper<ICustomEntry, CustomEntryHandler> CustomEntryMapper = new PropertyMapper<ICustomEntry, CustomEntryHandler>(ViewHandler.ViewMapper)
    { 
	    [nameof(ICustomEntry.Text)] = MapText,
	    
	    [nameof(ICustomEntry.TextColor)] = MapTextColor,
	    
	    };
    
	    protected override EditText CreatePlatformView()
	    {
		    return new EditText(Context);
	    }
    
	    static void MapText(EntryHandler handler, ICustomEntry entry)
	    {
		    handler.PlatformView?.Text = entry.Text;
	    }
    
	    static void MapTextColor(EntryHandler handler, ICustomEntry entry)
	    {
		    handler.PlatformView?.TextColor = entry.TextColor;
	    }
}

5. Create a custom control by subclassing the View class and implementing the control interface:

public class CustomEntry : View, ICustomEntry
{
    public string Text { get; set; }
    public Color TextColor { get; set; }
}

6. Register the handlers.

This is accomplished using the AddHandler method specifically on the MauiProgram class.

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
	    var builder = MauiApp.CreateBuilder();
	    builder.UseMauiApp<App>();
	    builder.ConfigureMauiHandlers(collection =>
	    {
	    //#if __ANDROID__
		    handlers.AddHandler(typeof(CustomEntry), typeof(CustomEntryHandler));
	    //#endif
	    });
	    return builder.Build();
    }
}

And our example is done!! 🎊

Event Subscription

The ViewHandler class also has the methods:

  • ConnectHandler is the ideal place to initialize and subscribe to events.
  • DisconnectHandler is great for disposing of objects and unsubscribe events, as you will see the example below:
public partial class CustomEntryHandler : ViewHandler<ICustomEntry, EditText>
{ 
// ...

 protected override void ConnectHandler(EditText platformView)
 {
  _defaultTextColors = platformView.TextColors;
  _defaultPlaceholderColors = platformView.HintTextColors;
  _watcher.Handler = this;
  platformView.AddTextChangedListener(_watcher);
  base.ConnectHandler(platformView);
 }

 protected override void DisconnectHandler(EditText platformView)
 {
  platformView.RemoveTextChangedListener(_watcher);
  _watcher.Handler = null;
  base.DisconnectHandler(platformView);
 }
}

Wrapping Up

I hope the information in the article has worked for you and is very useful in .NET MAUI!

See you next time! 🙋‍♀️

References

See Also


LeomarisReyes
About the Author

Leomaris Reyes

Leomaris Reyes is a Software Engineer from the Dominican Republic, with more than 5 years of experience. A Xamarin Certified Mobile Developer, she is also the founder of  Stemelle, an entity that works with software developers, training and mentoring with a main goal of including women in Tech. Leomaris really loves learning new things! 💚💕 You can follow her: Twitter, LinkedIn , AskXammy and Medium.

Related Posts

Comments

Comments are disabled in preview mode.