Search code examples
c#xamarin.formstimepicker

How can I tell if OK or Cancel was clicked on a TimePicker created with Xamarin.Forms?


I'm working on an android app which is based on Xamarin.Forms and I've created a custom dialog that shows a TimePicker (not TimePickerDialog).

So far everything works, except the fact that I've only found one way to check if the user made a selection in the TimePicker which is TimePicker.Unfocused.

Sadly that event does not return which of the two buttons in the picker was clicked : (

I tried working around this by saving the time with which I initially created the TimePicker and used that to compare if it got changed by the user. Now I've changed it so that it conveniently saves you the need to change the default time, and noticed that this is a problem now, since I have no longer any way of knowing which button was used to close the TimePicker.

var picker = new TimePicker() {
    // if 'minutes' is set, use it's value as default value for the picker, otherwise the day beginning
    Time = (minutes > -1 ? new TimeSpan(0, minutes, 0) : dayBegin),
};

picker.Unfocused += (sndr, evt) => {
    var tp = (TimePicker)sndr;
    var changed = tp.Time != oldTime;
    if (changed) {
        Debug.WriteLine("unfocused: " + tp.Time);
    }
    else {
        Debug.WriteLine("canceled?");
    }
    dialog.Close(cpDialog.DialogResult.Yes);
    // close my own dialog that showed the picker
};

It would be nice if the event for .Unfocused += would include the closing choice aside of just IsFocused. Or if there would be alternatively events for attaching like .ClickedCancel += and .ClickedOK +=.


Solution

  • The TimePicker Class lacks the event "TimeSelected" found for example in the DatePicker class ("DateSeleted")

    But!

    If you look up the TimePicker Class, you can see that there's some BindableProperties there.

    One of them is:

    public static readonly BindableProperty TimeProperty;

    That means that, in your xaml file, in the TimePicker block you can bind the TimeProperty to a property in your ViewModel, for example:

    <TimePicker x:Name="DeliveryTimePicker"
                Time="{Binding TimeValue}">
    </TimePicker>
    

    (TimeValue is a property of type TimeSpan I created in my ViewModel)

    That property will update when you click the "Ok" button in your TimePicker.

    (Which I believe is what you want!)

    (Further info)

    You can Bind directly in your xaml to the other BindableProperties as well, the way you do that is you type their name without the "property" part TimeProperty -> Time.

    You can also subscribe in your xaml to the PropertyChanged event and check if the name of the property is equal to the one you are trying to look for.

    For debug purposes, create that method, put a breakpoint and look for event.PropertyName, and watch the breakpoint being hit several times, the property's name will be different when creating the TimePicker, clicking Ok, etc.