Manchmal soll der Nutzer innerhalb einer App die Möglichkeit haben ein Datum auszuwählen. Für dieses Szenario stellt Xamarin.Forms das DatePicker-Control, welches durch das Xamarin.Forms.Visual.Material Package auch wunderbar in Material-Design dargestellt wird. Ich bin mit der Umsetzung allerdings nicht ganz glücklich, weil man keinen Placeholder-Text mitgeben kann, welcher erläutert, um was für ein Datum es sich gerade handelt. Daher wollen wir uns in diesem Beitrag anschauen, wie wir einen eigenen PlaceholderDatePicker schreiben können.

Wir beginnen damit ein neues Control mit dem Namen PlaceholderDatePicker zu erstellen, welches auf einen „normalen“ DatePicker zurückgreift. Diesem Control spendieren wir noch eine BindableProperty mit dem Namen Placeholder. Insgesamt erhalten wir also das folgende Control:

public class PlaceholderDatePicker : DatePicker
{
    public static readonly BindableProperty PlaceholderProperty
        = BindableProperty.Create(nameof(Placeholder), typeof(string), 
            typeof(PlaceholderDatePicker), default(string));

    public string Placeholder
    {
        get => (string)GetValue(PlaceholderProperty);
        set => SetValue(PlaceholderProperty, value);
    }
}

Für die Umsetzung müssen wir nun Custom Renderer für Android und iOS schreiben. Wir beginnen mit der Umsetzung für Android. Erstellt im Android-Projekt eine Klasse PlaceholderDatePickerRenderer, welche auf MaterialDatePickerRenderer zurückgreift und die Methode OnElementChanged überschreibt.

public class PlaceholderDatePickerRenderer : MaterialDatePickerRenderer
{
    public PlaceholderDatePickerRenderer(Context context) : base(context)
    {
    }

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

        if (Control != null && Element is PlaceholderDatePicker datePicker 
            && !string.IsNullOrWhiteSpace(datePicker.Placeholder))
        {
            Control.HintEnabled = true;
            Control.Hint = datePicker.Placeholder;
        }
    }
}

Es wird also geschaut, ob die Placeholder-Eigenschaft gefüllt ist. Wenn dies der Fall ist, dann setzen wir die HintEnabled-Eigenschaft auf true und setzen den Placeholder-Text als Hint-Eigenschaft. Damit wir uns nun der Placeholder bereits unter Android angezeigt, sofern wir noch das ExportRenderer-Attribut hinzufügen.

[assembly: ExportRenderer(typeof(PlaceholderDatePicker), 
    typeof(PlaceholderDatePickerRenderer), 
    new[] { typeof(VisualMarker.MaterialVisual) })]

Für iOS fügen wir eine Klasse PlaceholderDatePickerRenderer dem iOS-Projekt hinzu, welche auf MaterialDatePickerRenderer zurückgreift und das Interface IMaterialEntryRenderer implementiert. Anders als unter Android müssen wir nun die Eigenschaft Placeholder aus dem Interface angeben und geben hier, sofern gesetzt, den Placeholder-Text zurück.

public class PlaceholderDatePickerRenderer : MaterialDatePickerRenderer, 
        IMaterialEntryRenderer
{
    string IMaterialEntryRenderer.Placeholder
    {
        get
        {
            if (Element is PlaceholderDatePicker datePicker
                && !string.IsNullOrEmpty(datePicker.Placeholder))
            {
                return datePicker.Placeholder;
            }

            return string.Empty;
        }
    }
}

Auch hier müssen wir wieder das ExportRenderer-Attribut angeben.

[assembly: ExportRenderer(typeof(PlaceholderDatePicker), 
    typeof(PlaceholderDatePickerRenderer), 
    new[] { typeof(VisualMarker.MaterialVisual) })]

Damit können wir das neue PlaceholderDatePicker-Control nun in unserer App verwendet und uns wird der Placeholder-Text bei Wunsch direkt angezeigt, wie der folgende Screenshot verdeutlicht.

Ihr findet den gesamten Code auch auf GitHub und könnt dieses somit ganz einfach in eure nächsten Projekte integrieren.