Basics of Xamarin Forms Custom Renderers

There is plenty of great documentation detailing how to use custom renderers in Xamarin Forms, such as Customizing Controls an Each Platform. It is a heavy read and possibly a little confusing for new comers to Xamarin Forms, hence I am going to give you the quick basic overview of Custom Renderers and how to use them.

What is a Custom Renderer?

Xamarin Forms control’s are NOT rendered directly on the native platform. They are passed into a renderer and converted to a native control. By converted, that means a new instance of a native control is created, the properties from the Xamarin Forms control are translated across to the native control, then the native control is placed in the native layout, which then gets rendered by the platform.

That is all they do, input a Xamarin Forms control, output a native control. The Xamarin Forms control is nothing but an object with some values and methods used for transporting information back and forth between the Native Platform and the Xamarin Forms framework.

Xamarin Forms Custom Renderers Example

Example: Xamarin Forms Entry Control into its native component

How to Implement a Custom Renderers

Custom Renderers are platform specific, hence you need to create a custom renderer for all platforms you want the control displayed on. You create a class that inherits from ViewRenderer and then you declare it with an assembly attribute ExportRenderer. Then create the Native Control in the OnElementChanged method that you override as demonstrated below.

[assembly: ExportRenderer(typeof(XamarinFormsControl), typeof(CustomRenderer))]
namespace Mobile.Droid.Renderers
{
   public class CustomRenderer: ViewRenderer<XamarinFormsControl, NativeControl>
   {
        protected override void OnElementChanged(ElementChangedEventArgs<XamarinFormsControls> e)
        { 
             base.OnElementChanged(e);
             SetNativeControl(new NativeControl());
        }
   }
}

This is great if you are implementing a native control that has no corresponding Xamarin Forms Control.

Modifying a Custom Renderer

Xamarin Forms has plenty of renderers for all of its controls and it is always best to use these if possible. Sometimes the framework renderers don’t provide a way to customize a specific property and you need to do this yourself via a Custom Renderer. You can inherit from existing renderers, call base.OnElementChanged(e) to ensure the existing rendering completes, then add your customization. In the example below I am just changing the text color to black on an Entry control but you can do whatever you want with the native control.

[assembly: ExportRenderer(typeof(Entry), typeof(TextFieldRenderer))]
namespace Mobile.Droid.Renderers
{
   public class TextFieldRenderer: EntryRenderer
   {

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
             base.OnElementChanged(e);

             var nativeControl = Control;

             nativeControl.SetTextColor(Android.Graphics.Color.Black);
        }
    }
}

 

OnElementChanged Usage

OnElementChanged gets called many times for different reasons, as such Control, NewElement and OldElement may or may not be null. Follow the below rules to handle each situation.

if (Control == null) {
    // Create the native control and use SetNativeControl
    // Do not assign directly to the Control property unless you know what you are doing
}

if (e.OldElement != null) {
    // Cleanup resources and remove event handlers for this element.
}

if (e.NewElement != null) {
    // Use the properties of this element to assign to the native control, which is assigned to the base.Control property
}

Note: The Xamarin documentation mentions to assign directly to the Control property. I don’t recommend this as the SetNativeControl function assigns to the Control property but also performs removal of event subscriptions, sets FocusChange events and numerous other operations. You would be losing all of this and opening yourself to memory leaks if you assign directly to the Control.

Learn More

If you want to learn more about Custom Renderers, have a look at Xamarin’s documentation Customizing Controls on Each Platform

Microsoft MVP | Xamarin MVP | Xamarin Certified Developer |
Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia

Related Posts

5 Comments

  1. angrydeveloper

    Any ideas why custom renderer created in specified ios library project doesnt render anything in app?

    I Have ExportRendererAttribute included, OnElementChanged overrided with:

    if (Control == null)
    {
    var uiView = new UIView(new CGRect(0, 0, 400, 30));
    var dateDisplay = new UITextView();
    dateDisplay.Text = “2000 – 01 – 01”;
    dateDisplay.Frame = new CGRect(0, 0, uiView.Bounds.Width, uiView.Bounds.Height);
    uiView.AddSubview(dateDisplay);
    SetNativeControl(uiView);
    }

    1. Adam Pedley

      First, I assume you have added a breakpoint in that code and know that its actually executing. Just to make sure the renderer is being picked up and run.

      If so, I would try with that renderer on a blank page, just to make sure nothing else is covering it. You could also test this by making the background color of the UIView something different to see if you can grab some visual indication of where it is.

      If you have Inspector (https://xamarinhelp.com/xamarin-inspector-live-apps/) you can also use that to see where it is in the visual layers.

  2. Daniel

    Hi Thank you for explaining the way to use renderers. I’m trying to implement a new custom render using the above example without luck.

    This is what I want to do for when I am running a UWP device and want to display a Passwordbox instead of the Entry with ispassword = true:

    [assembly: ExportRenderer(typeof(CustomPasswordBox), typeof(PasswordBoxRenderer))]
    namespace App.UWP.CustomRenderer
    {
    public class PasswordBoxRenderer : ViewRenderer
    {
    public PasswordBoxRenderer()
    {
    }

    protected override void OnElementChanged(ElementChangedEventArgs e)
    {
    base.OnElementChanged(e);
    SetNativeControl(new Windows.UI.Xaml.Controls.PasswordBox());
    }
    }
    }

    I can’t build this code.
    Hovering my mouse over the PasswordBoxRenderer class I get the error: CustomPasswordBox cannot be used as type parameter TElement…. There is no implicit reference conversion from Passwordbox to xamarin.forms.view.

    It would be nice to see this work.

    1. Adam Pedley

      The TElement needs to be a Xamarin.Forms control. So you would use Entry.

      When you SetNativeControl, this is what creates a new PasswordBox.

      However you don’t want all your Entry controls turning to a PasswordBox, So you create a CustomPasswordBox that inherits from Entry, and use the CustomPasswordBox in your XAML.

      Then the assembly attribute will be as
      [assembly: ExportRenderer(typeof(CustomPasswordBox), typeof(PasswordBoxRenderer))]

      I am assuming that CustomPasswordBox, isn’t inheriting from Entry at the moment.

Leave A Comment?