Xamarin.Forms Controls: RepeaterView mit DataTemplateSelector

Ich habe ja bereits gezeigt, wie wir ein neues Xamarin.Forms Control, nämlich die RepeaterView, erstellen und diese haben wir bereits erweitert, dass jede zweite Zeile eine andere Hintergrundfarbe bekommt. In diesem Beitrag möchte ich euch jetzt zeigen, wie ihr die RepeaterView so ergänzen könnt, dass statt eines ItemTemplates auch ein DataTemplateSelector angegeben kann, welcher auf Grund verschiedener Regeln das passende Template auswählt und darstellt.

Dazu benötigen wir natürlich eine neue BindableProperty, welche wir ItemTemplateSelectorProperty nennen wollen.

public static readonly BindableProperty ItemTemplateSelectorProperty =
    BindableProperty.Create(nameof(ItemTemplateSelector), typeof(DataTemplateSelector),
       typeof(RepeaterView));

public DataTemplateSelector ItemTemplateSelector
{
    get => (DataTemplateSelector)GetValue(ItemTemplateSelectorProperty);
    set => SetValue(ItemTemplateSelectorProperty, value);
}

Nun müssen wir noch die Methode ViewFor anpassen. Diese überprüft nun zunächst, ob ein ItemTemplateSelector angegeben ist. Sollte dies der Fall sein, wird dieser verwendet, um das richtige Template zu generieren. Ansonsten greift die alte Logik und wir erstellen eine Instanz von unserem ItemTemplate.

protected virtual View ViewFor(object item, bool isEvenRow = false)
{
    if (ItemTemplateSelector == null && ItemTemplate == null)
        return null;

    object content = null;
    if (ItemTemplateSelector != null)
    {
        var template = ItemTemplateSelector.SelectTemplate(item, this);
        if (template != null)
            content = template.CreateContent();
    }
    else
    {
        content = ItemTemplate.CreateContent();
    }

    if (content == null)
        return null;

    var view = content is ViewCell viewCell ? viewCell.View : content as View;

    view.BindingContext = item;

    if (ItemTappedCommand != null)
        AddTapGestureToChildView(view);

    if (IsAlternateRowColorEnabled)
    {
        if (isEvenRow)
            view.BackgroundColor = AlternateRowColor;
    }

    return view;
}

Damit haben wir unsere RepeaterView schon soweit angepasst, dass wir anstatt eines ItemTemplates auch einen DataTemplateSelector angegeben können. Ich habe das bestehende Beispiel als Grundlage verwendet und unser Datenmodell um die Angabe des Geschlechts ergänzt. Bei weiblichen Personen wird soll nun eine pinke Box als Indikator dienen und bei männlichen Personen eine blaue. Dafür erstellen wir uns nun einen PersonDataTemplateSelector, welcher vom Typ DataTemplateSelector ableitet.

public class PersonDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate FemaleDataTemplate { get; set; }
    public DataTemplate MaleDataTemplate { get; set; }

    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {
        if (item is Person person)
        {
            switch (person.Gender)
            {
                case Gender.Male:
                    return MaleDataTemplate;
                case Gender.Female:
                    return FemaleDataTemplate;
            }
        }

        return null;
    }
}

Nun können wir in XAML eine Instanz des PersonDataTemplateSelectors erstellen und müssen nur die beiden DataTemplates angeben.

<utils:PersonDataTemplateSelector 
    x:Key="PersonDataTemplateSelector"
    FemaleDataTemplate="{StaticResource FemaleDataTemplate}"
    MaleDataTemplate="{StaticResource MaleDataTemplate}" />

Somit erhalten wir in unserem Beispiel die folgende Ausgabe:

Das gesamte Beispiel befindet sich natürlich wieder auf GitHub und steht jedem für Erweiterungen zur Verfügung.

Extension Methods: Object Erster Emulator für das Surface Duo veröffentlicht WordPress-Seite als Xamarin.Forms App – Teil 2