Taoffi's blog

prisonniers du temps

Xamarin forms: an inside look – II. The (simplified) journey of a Label from your code to screen

Understanding how your UI code ends up by being shapes and colors on a device screen may help in better usage, better interpretation for encountered issues and for evaluating if you really need a custom renderer for a given control.

Exploring this also explains some of the interesting internal Xamarin forms mechanisms to play its awesome cross-platform game!

To do this, I will here attempt to explore the journey of a simple control: The Label.

For simplicity, I will track the journey to an Android device.

Label hierarchy

Label is a class defined Xamarin.Forms.Core.dll. Its hierarchy is roughly the following:

 

The Label renderer

At the end of this simple control processing chain, we have the android's Label renderer responsible of drawing it on the screen of each device… The renderer hierarchy (on Android):

The mono component

The ViewRenderer (XF Platform.Android.dll) is defined as:

public abstract class ViewRenderer<TView, TNativeView>

: VisualElementRenderer<TView>,

global::Android.Views.View.IOnFocusChangeListener,

IJavaObject,

IDisposable

 

It inherits the VisualElementRenderer (abstract) class which is defined as:

public abstract class VisualElementRenderer<TElement>

: FormsViewGroup,

IVisualElementRenderer,

IRegisterable,

IDisposable,

global::Android.Views.View.IOnTouchListener,

IJavaObject,

global::Android.Views.View.IOnClickListener

where TElement : VisualElement

 

Both of them refer to objects from the Android.Views and Android.Runtime namespaces defined in Mono.Android.dll.

 

The Label renderer referenced types, inheritance and interface implementations (summary)

 

Label renderer calls (summary)

The IRegisterable and Registrar link nodes

As you can notice, both ViewRenderer and VisualElementRenderer implement the IRegisterable Interface defined in XF.Core.dll.

 

IRegistrable is implemented by all Renderers. And is referenced by the Registrar class (we will see later).

Let us follow IRegistrable implemented child tree till the Label Renderer node:

(Incidentally, in he above figure, we again notice our ImageSourceHandler at the very root of the tree… you may look at my notes here)

The key node: XF Registrar

Registrar (Xamarin.Forms.Core.dll) is an internal static class. It exposes (internally) some methods for registering generic handlers of which we find the Renderers.

The method RegisterAll(Type[] attrTypes) of the Registrar class proceeds registration of the input array of types (note: as the class is internal, I could not find – for now – who calls this method: see a sample call at the end of this post).

If we follow the method's decompiled code, we understand that items of the Type array argument are expected to be each decorated with an attribute of type HandlerAttribute (deriving from System.Attribute). Here is a simplified version of the method's code:

 

internal static void RegisterAll(Type[] attrTypes)
{
    Assembly[] assemblies = Device.GetAssemblies();

    foreach (Assembly assembly2 in assemblies)
    {
        foreach (Type type in attrTypes)
        {
            Attribute[] attributeArray = Enumerable.ToArray<Attribute>(CustomAttributeExtensions.GetCustomAttributes(assembly2, type));
            foreach (HandlerAttribute attribute in attributeArray)
            {
                if (attribute.ShouldRegister())
                {
                    Registered.Register(attribute.HandlerType, attribute.TargetType);
                }
            }
        }
    }
}

 

 

HandlerAttribute exposes two members: HandlerType and TargetType, both are of type System.Type

 

Few attributes derive from this HandlerType attribute. Of which you have… oh… the famous ExportRendererAttribute!

 

And that is roughly how XF finds the renderer to call for a given control on each platform.

Sample call to Registrar at droid application launch in AppCompat:

Comments are closed