Home > database >  Custom Picker Renderer bug - Picker displays twice upon calling Picker.Focus()
Custom Picker Renderer bug - Picker displays twice upon calling Picker.Focus()

Time:12-31

I am trying to employ a custom renderer for my Picker controls. I also need my Picker to fire up when I open a tab. I do this by calling the picker's Focus() method on tab SelectionChanged.

if (e.NewPosition == 1)
{
    myPicker.Focus();
}

This, however, fires up two instances of the picker alert at the same time; one is the default renderer, the second one is my custom renderer. They are one atop the other, such that when I close the one with my custom renderer, the one with default renderer is visible.

Simply tapping the Picker will display only one instance, with the custom renderer (this works as intended).

I wrote my custom renderer following this post's answer.

I tried the answer described here, but the problem is that this skips over the second instance of the picker, which is not what I need. I need to keep the instance that has my custom renderer, not the one with the default renderer.

I also tried to make sure that I am running on the right thread, implementing code described in this question's answers.

Moreover, I tried to somehow remove events from the CustomRenderer and add them again, like this:

protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Picker> e)
{
    base.OnElementChanged(e);
    Control.Click  = null; // hoping this would override all existing events
    Control.Click  = Control_Click;
}

Finally, this question came closest to my situation and I tried following the solutions described in the answers.

None of these worked. I believe that when Focus() is called, somehow the default renderer shows up first due to my custom renderer inheriting the default PickerRenderer.

How do I enforce the custom renderer?

Or is there a different way for me to fire up my picker upon changing tabs, instead of calling Focus()?

My project runs on Xamarin.Forms 5.0.0.2545 (latest version as of when I'm writing this question).

EDIT

I observed the following behaviour: Control.Click event is fired AFTER the default renderer is displayed. By debugging the app and placing a break point inside my Control.Click handler function, I can see that the app first opens the default picker, and then it halts in said breakpoint.

CodePudding user response:

SOLVED

By studying the PickerRenderer.cs class, I realised that there were more functions that had to be overwritten.

To begin with, I made my custom renderer class implement the IPickerRenderer interface and added the following function:

void IPickerRenderer.OnClick()
{
    Control_Click(this, null); // this function handles the Control.Click event
}

Moreover, I overwrite the CallOnClick() function:

public override bool CallOnClick()
{
    Control_Click(this, null); // same function, that handles the Control.Click event
    return true;
}

Finally, I added this bit of code (thanks to this answer) that ensures the Picker shows up only once. Thus, my OnElementChanged function looks like this:

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

    if (Control != null)
    {
        Control.Focusable = false;
    }

    Control.Click  = Control_Click; // this is where I link the handler to the event
}

The conclusion is that the described behaviour either

  • wasn't a bug, which means I just hadn't implemented it correctly
  • was a bug, and I managed to find a good workaround

Either way, I managed to solve my problem.

If anyone else stumbles upon this, I hope my work helps.

  • Related