Erstellen eines neuen Xamarin.Forms-Element mit Renderern

Abgeschlossen

Das Ableiten von vorhandenen Renderern und Verbessern ihres integrierten Verhaltens funktioniert hervorragend, wenn ein Xamarin.Forms-Element vorhanden ist, das bereits das meiste von dem erledigt, was wir brauchen. Aber wenn wir ein Steuerelement wünschen, das in Xamarin.Forms überhaupt noch nicht vorhanden ist, unterscheiden sich die Schritte geringfügig, und ein wenig mehr Arbeit ist zu tun.

Wir benötigen ein Xamarin.Forms-Element und einen Renderer. Außerdem benötigen wir ein natives Steuerelement, das auf jeder Plattform verwendet werden kann. Wir möchten z.B. ein Steuerelement, das dem Benutzer ermöglicht, auf dem Bildschirm zu zeichnen, aber weder in iOS noch in Android ist ein solches integriertes natives Steuerelement vorhanden. Wir müssen es also entweder erstellen oder Drittanbieterimplementierungen in beiden Plattformen suchen.

In dieser Unterrichtseinheit werden wir ein benutzerdefiniertes Xamarin.Forms-Element und einen Renderer zum Erstellen einer Zeichen-App erstellen.

Erstellen eines Elements

Beim Anpassen eines Elements und eines Renderers haben wir die vorhandene Implementierung als Basisklasse verwendet. Jetzt erstellen wir aber ein ganz neues Element. Da View das einfachste Xamarin.Forms-Element ist, verwenden wir es als Basisklasse für das neue Element:

public class SketchView : View
{
...
}

Hinzufügen von Elementeigenschaften

Die meisten Elemente haben einige Konfigurationsoptionen oder Werte, die mit dem nativen Steuerelement gemeinsam genutzt werden müssen. Integrierte Steuerelemente haben tendenziell zu viele Eigenschaften, die festgelegt werden können. Label hat beispielsweise Text, FontSize und viele andere. Für benutzerdefinierte Elemente müssen wir entscheiden, welche Eigenschaften sinnvoll sind. Unsere Implementierung von SketchView verfügt z.B. über eine InkColor-Eigenschaft zum Ändern der Farbe der Linie, die wir zeichnen.

Wenn wir Eigenschaften für Elemente erstellen, sollten wir BindableProperty verwenden. Mit bindbaren Eigenschaften können wir die Datenbindung auf den Seiten verwenden, die das neue Element verwenden. Der wichtigere Vorteil der bindbaren Eigenschaften ist jedoch, dass der Renderer immer dann benachrichtigt wird, wenn ein Wert geändert wird:

public class SketchView : View
{
    public static readonly BindableProperty MultiTouchEnabledProperty = BindableProperty.Create("MultiTouchEnabled", typeof(bool), typeof(SketchView), false);

    public bool MultiTouchEnabled
    {
        get => GetValue(MultiTouchEnabledProperty);
        set => SetValue(MultiTouchEnabledProperty, value);
    }
}

Erstellen von Renderern für ein benutzerdefiniertes Element

Wir leiten von der ViewRenderer<TView, TNativeView>-Basisklasse ab, um Renderer für ein neues Element zu erstellen. Die Typparameter werden auf das neue Xamarin.Forms-Element (TView) festgelegt und das native Steuerelement (TNativeView) entsprechend.

Angenommen, wir haben ein Android-Steuerelement mit dem Namen AndroidPaintView, dann würde die Klassendeklaration des Android-Renderers für SketchView wie folgt aussehen:

public class SketchViewRenderer : ViewRenderer<SketchView, AndroidPaintView>
{
...
}

Erstellen des nativen Objekts in OnElementChanged

In der OnElementChanged-Methode müssen wir das native Steuerelement erstellen. Dies unterscheidet sich etwas von dem Anpassungsworkflow, wo wir uns darauf verlassen konnten, dass es von der Basisklasse erstellt wird. Wir instanziieren zunächst das native Objekt. Dann rufen wir SetNativeControl auf, wodurch die Control-Eigenschaft des Renderers gefüllt wird.

OnElementChanged könnte mehrmals von der Plattform aufgerufen werden, aber der Renderer sollte Steuerelemente OnElementChanged mehrmals instanziieren, weshalb wir eine Wächterklausel für diesen Teil des Codes verwenden, um zu überprüfen, ob Control bereits festgelegt ist:

protected override void OnElementChanged(...)
{
    ...

    if (Control == null) // Create native control only if it hasn't been done before
    {
        SetNativeControl(new AndroidPaintView());
    }
}

Der Renderer hat über die Element-Eigenschaft automatisch Zugriff auf das Xamarin.Forms-Element. Nachdem wir SetNativeControl aufgerufen haben, hat er auch über die Control-Eigenschaft Zugriff auf das native Steuerelement.

Verarbeiten von Änderungen in bindbaren Eigenschaften

Wenn wir unsere Elemente mit bindbaren Eigenschaften entwickelt haben, muss unser Renderer in der Lage sein, vom App-Code vorgenommene Änderungen an diesen Eigenschaften zu verarbeiten. Wir können diese Änderungen durch Überschreiben der OnElementPropertyChanged-Methode verarbeiten. Das Überschreiben wird immer dann aufgerufen, wenn eine BindableProperty im Element geändert wird. Da es für alle bindbaren Eigenschaften aufgerufen wird, müssen wir den überprüfen und benutzerdefinierte Logik für jede Eigenschaft verwenden, die der Renderer verarbeitet. Unsere Logik tut alles, was erforderlich ist, um den Wert zu konvertieren und in das native Objekt zu kopieren:

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);

    if (e.PropertyName == SketchView.InkColorProperty.PropertyName)
    {
        Control.SetInkColor(Element.InkColor.ToAndroid());
    }
}