Search code examples
c#xamarinxamarin.formscustom-renderer

Get the type of calling ContentPage of a PageRenderer within a ExportRenderer


I have been following this answer in order to tell if me when my Xamarin Page has loaded. https://stackoverflow.com/a/63592259/560476

The rough idea is that once the PageRenderer has attached to the Window it will fire the PageLoaded message on to the MessagingCenter and my MainPage that is subscribed to that message will then react.

However the problem with this implementation is that anytime a ContentPage triggers OnAppearing it will trigger PageLoaded to be sent regardless of the ContentPage as it applies to them all.

I wonder if it is possible to get the type that is calling the ExportRenderer as I could then do something like MessagingCenter.Send(new object(), $"{typeof(MainPage)}Loaded"); and then I would only be subscribing to the ContentPage's where I want this.

[assembly: ExportRenderer(typeof(ContentPage), typeof(AdvancedPageRenderer))]
namespace MyRunCompanion.Droid.Renderer
{
    public class AdvancedPageRenderer : PageRenderer
    {
        public AdvancedPageRenderer(Context context) : base(context)
        {
            AutoPackage = false;
        }

        protected override void OnAttachedToWindow()
        {
            base.OnAttachedToWindow();

            MessagingCenter.Send(new object(), "PageLoaded");
        }
    }
}
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();

        MessagingCenter.Subscribe<object>(new object(), "PageLoaded", (sender) =>
        {
            // Do something whenever the "PageLoaded" message is received
            Console.WriteLine("Do something whenever the PageLoaded message is received");
        });
    }
}

Solution

  • A better approach would be to test in the custom renderer and only send the message when the ContentPage that is being renderered is a MainPage Class (desired class) instance. This can be achieved using Element property:

    protected override void OnAttachedToWindow()
    {
        base.OnAttachedToWindow();
        if (Element is MainPage)
            MessagingCenter.Send(new object(), "PageLoaded");
    }
    

    But if for some reasons you want to stick with what you described in the question then you can use:

    MessagingCenter.Send(new object(), Element.GetType().Name + "Loaded");