Xamarin.Forms Controls: RepeaterView mit alternativen Zeilenfarbe

Ich habe bereits gezeigt, wie man sich ganz einfach eine RepeaterView erstellen kann. Nun möchte ich die bestehende Implementierung so erweitern, dass jede zweite Zeile eine andere Hintergrundfarbe hat. Dies hat den großen Vorteil, dass sich die Lesbarkeit der Daten deutlich erhöht und man einen größeren Kontrast zwischen den einzelnen Einträgen herstellen.

Wir öffnen unsere Klasse RepeaterView.cs und fügen zwei neue BindableProperties hinzu. Zum einen wollen wir die alternative Zeilenfarbe ein- bzw. ausschalten und zum anderen wollen wir die Hintergrundfarbe individuell einstellen. Daher erhalten wir die beiden folgenden Einträge:

public static readonly BindableProperty IsAlternateRowColorEnabledProperty =
    BindableProperty.Create(nameof(IsAlternateRowColorEnabled), typeof(bool), 
	  typeof(RepeaterView), false);

public bool IsAlternateRowColorEnabled
{
    get => (bool)GetValue(IsAlternateRowColorEnabledProperty);
    set => SetValue(IsAlternateRowColorEnabledProperty, value);
}

public static readonly BindableProperty AlternateRowColorProperty =
    BindableProperty.Create(nameof(AlternateRowColor), typeof(Color), 
	  typeof(RepeaterView), Color.Black);

public Color AlternateRowColor
{
    get => (Color)GetValue(AlternateRowColorProperty);
    set => SetValue(AlternateRowColorProperty, value);
}

Nun passen wir die Methode ViewFor an. Dafür ergänzen wir den optionalen Parameter isEvenRow vom Typ bool, welcher später angibt, ob es sich um eine gerade Zeile handelt. Ebenso fügen wir die Logik hinzu, dass validiert wird, ob die alternative Zeilenfarbe aktiviert ist und sollte isEvenRow auf true stehen, so wird die Hintergrundfarbe entsprechend angepasst. Somit erhalten wir die folgende Methode:

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

    var content = ItemTemplate.CreateContent();

    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;
}

Im nächsten Schritt passen wir die Methode ItemsSourcePropertyOnChanged an, denn innerhalb dieser Methode können wir ermitteln, ob es sich um eine gerade Zeile und diese Information entsprechend an die ViewFor-Methode übergeben. Wir erhalten dann die folgende Methode:

private static void ItemsSourcePropertyOnChanged(BindableObject bindable, 
    object oldValue, object newValue)
{
    if (!(bindable is RepeaterView control))
        return;

    control.Children.Clear();

    var collection = (ICollection)newValue;
    if (collection == null)
        return;

    if (collection is INotifyCollectionChanged observableCollection)
        control.AddCollectionNotificationsListener(observableCollection);

    var isEvenRow = false;
    foreach (var item in collection)
    {
        control.Children.Add(control.ViewFor(item, isEvenRow));
        isEvenRow = !isEvenRow;
    }
}

Nun müssen wir abschließend noch die Methode ObsersavableCollectionOnCollectionChanged anpassen. Hier fügen wir am Anfang ein If-Statement hinzu, denn sollte die alternative Zeilenfarbe aktiviert sein, so müssen wir bei einer Veränderung der ItemsSource die vollständige Liste neu berechnen. Die bestehende Logik wandert dann in den Else-Zweig. Hier der Code-Ausschnitt, welcher eingefügt werden muss:

if (IsAlternateRowColorEnabled)
{
    Children.Clear();

    var isEvenRow = false;
    foreach (var item in (ICollection)s)
    {
        Children.Add(ViewFor(item, isEvenRow));
        isEvenRow = !isEvenRow;
    }
}

Damit können wir die neue Funktionalität bereits verwenden und der folgende Screenshot zeigt das Ergebnis:

Der gesamte Code befindet sich natürlich auch wieder auf GitHub und ich bin jetzt schon gespannt, wie wir die RepeaterView noch weiter verbessern können.

FontAwesome in Xamarin.Forms-Apps Eigene Schriftarten in Xamarin.Forms StatusBar unter Android, iOS und UWP einfärben