MvvmCross – Xamarin.Android Popup DatePicker on EditText Click

Goal

When the user clicks on an EditText box in a MvvmCross Xamarin.Android app show a date picker popup.

Screenshot_2014-04-24-15-09-55

Research

Solution

All of the solutions I kept finding to this problem always had the user clicking on a button to show the DatePicker popup, and I really wanted the user to be able to show the date picker when they pressed on the EditText box, much like Android does in the default Calendar app.

From the above articles I was able to piece together a solution, the highlights:

datePickerText = view.FindViewById<EditText>(Resource.Id.DatePickerEditText);            
datePickerText.Click += delegate
{
    var dialog = new DatePickerDialogFragment(Activity, Convert.ToDateTime(datePickerText.Text), this);
    dialog.Show(FragmentManager, "date");
};

The full solution:

public class EnterTimeView : MvxFragment, DatePickerDialog.IOnDateSetListener
{
    private EditText datePickerText;
    
    public EnterTimeView()
    {
        this.RetainInstance = true;
    }

    public override Android.Views.View OnCreateView(Android.Views.LayoutInflater inflater, Android.Views.ViewGroup container, Android.OS.Bundle savedInstanceState)
    {
        this.HasOptionsMenu = true;
          
        var ignored = base.OnCreateView(inflater, container, savedInstanceState);
        var view = inflater.Inflate(Resource.Layout.EnterTimeView, container, false);

        datePickerText = view.FindViewById<EditText>(Resource.Id.DatePickerEditText);
        datePickerText.Focusable = false;
        datePickerText.Click += delegate
        {
            var dialog = new DatePickerDialogFragment(Activity, Convert.ToDateTime(datePickerText.Text), this);
            dialog.Show(FragmentManager, "date");
        };

        var set = this.CreateBindingSet<EnterTimeView, EnterTimeViewModel>();
        set.Bind(datePickerText).To(vm => vm.Date);
        set.Apply();

        return view;
    }
             
    public void OnDateSet(Android.Widget.DatePicker view, int year, int monthOfYear, int dayOfMonth)
    {
        datePickerText.Text = new DateTime(year, monthOfYear + 1, dayOfMonth).ToString();
    }

    private class DatePickerDialogFragment : Android.Support.V4.App.DialogFragment 
    {
        private readonly Context _context;
        private DateTime _date;
        private readonly DatePickerDialog.IOnDateSetListener _listener;

        public DatePickerDialogFragment(Context context, DateTime date, DatePickerDialog.IOnDateSetListener listener)
        {
            _context = context;
            _date = date;
            _listener = listener;
        }

        public override Dialog OnCreateDialog(Bundle savedState)
        {
            var dialog = new DatePickerDialog(_context, _listener, _date.Year, _date.Month - 1, _date.Day);
            return dialog;
        }
    }
}