9

I am using an Xamarin.Forms.Picker control and handling the SelectedIndexChanged event.

The user scrolls thru the items in the picker control then the user selects the "Done" button that is prebuilt into the picker control. Is there anyway to capture when the user presses "Done" instead of when the index changes.

The index can change multiple times as the user scrolls thru the items and I don't want to handle unnecessary events as I only care about the last item selected.

Thanks in advance

<Picker x:Name="PickerMinStars" Title="Min number of 5 stars"  SelectedIndexChanged="Handle_PickerStarsSelectedIndexChanged">
        </Picker>
Jason Smith
  • 373
  • 2
  • 6
  • 20

4 Answers4

14

There are three workarounds to achieve your requirement.

Simple

set unfoucus event on Picker , it triggers when the picker are going to dismiss (click on the Done button or the outside area of the picker).

Medium

delay the SelectedIndexChanged event firing until after you tap Done button.

picker.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);

Complex

create Custom Renderers to handle Done button click event.

public class MyPickerRenderer : PickerRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
    {
        base.OnElementChanged(e);

        if(e.OldElement != null)
        {
            var toolbar = (UIToolbar)Control.InputAccessoryView;
            var doneBtn = toolbar.Items[1];

            doneBtn.Clicked -= DoneBtn_Clicked;
        }

        if(e.NewElement != null)
        {
            var toolbar = (UIToolbar)Control.InputAccessoryView;
            var doneBtn = toolbar.Items[1];

            doneBtn.Clicked += DoneBtn_Clicked;
        }
    }

    void DoneBtn_Clicked(object sender, EventArgs e)
    {
        Console.WriteLine("Clicked!!!!");
    }
}

Refer to

How can we handle the done button click event for a Xamarin Forms Picker?

Picker Selection Event

Community
  • 1
  • 1
ColeX
  • 14,062
  • 5
  • 43
  • 240
  • I have updatet from .forms 2.3.x to 3.1 and noted, that the behavior to the event SelectedIndexChanged has changed (old: after "Done", new by every change). I have replaced the SelectedIndexChanged- to the Unfocused event (as suggested here) and it works. If you also do that and access the SelectedIndex property to the picker, you have to handle the cancel case in Android (if (SelectedIndex = -1) {return} or similar). – FredyWenger Aug 21 '18 at 11:58
5

To handle the selection change event from XAML code, as Pieter Nijs has suggested in his blog

<Picker ItemsSource="{Binding FooList}"
    SelectedItem="{Binding SelectedFoo}"
    ItemDisplayBinding="{Binding Name}"
    iOSSpecific:Picker.UpdateMode="WhenFinished" />

This requires to add reference of

xmlns:iOSSpecific="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"

Which will raise selected index changed event after tapping ok.

Mukesh Modhvadiya
  • 2,178
  • 2
  • 27
  • 32
1

You can bind the SelectedItem to a property in your ViewModel. The property will only update when the data is changed.

<Picker SelectedItem="{Binding SelectedItemProperty}" />
lowleetak
  • 1,362
  • 1
  • 10
  • 19
0
public BindablePicker() 
{
    if (Device.OS == TargetPlatform.iOS) 
    {
        this.Unfocused += OnUnfocused; 
    }
    else
    {
        this.SelectedIndexChanged += OnSelectedIndexChanged; 
    } 
} 

private void OnUnfocused(object sender, FocusEventArgs e) 
{ 
    OnSelectedIndexChanged(sender, e);
} 

That way, Android will use the "Standard" way of handling the index change and iOS will wait until the "Done"-button is tapped.

testing
  • 19,681
  • 50
  • 236
  • 417