Events in Blazor

Jedes UI reagiert auf den Benutzer, nicht immer sofort, aber irgendwann doch. Der Entwickler verdrahtet z.B. den Button und ein Mausklick mit einem Stück Code. Meist eine Prozedur. In .NET basiert das irgendwie alles auf Delegates. Ich kann mich noch gut erinnern. Sitze bei Microsoft und jemand namens Barth versucht Delegates zu erklären. 10 Jahre habe ich daran noch gelitten und bis heute nicht verstanden was er gesagt hat.

Jedenfalls ist das heute mit Blazor ganz einfach. Einem @onclick wird ein Methodenname (als String) zugewiesen.

   1:  <button @onclick="btn">btn</button>
   2:  @code {
   3:      void btn()
   4:          {
   5:   
   6:          }

So weit so gut. Allerdings kann man die Methode btn auch Parametrisieren mit EventArgs oder noch besser MouseEventargs. Mal so mal so, kennt man ja eher aus JavaScript. Microsoft nutzt einen speziellen Event Typ um das zu realisieren EventCallback.

Wir werden uns das nun ein wenig zu Gemüte führen warum und wieso, aber zunächst einmal der Step Back zu den .NET Events. Seit .NET 2 helfen Action und Func um der Delegate Hölle ein wenig zu entkommen. Beides steht auch in Blazor zur Verfügung.

Der Anwendungsfall: eine Komponente löst ein Event aus, das eine Parent Komponente behandeln möchte. Ganz wie der Button, der in einer Page lebt.

Eine Blazor Komponente (das Ding ohne Route) soll also ein Event Auslösen (ein Button, Timer oder auch was aus der JS Browser API). Dazu bekommt die Komponente einen Parameter.

   1:   [Parameter]
   2:   public Action OnAction { get; set; }

Irgendeine Logik in der Komponente hat dann die dankbare Aufgabe das Event aufzurufen. Da das Event ungebunden und damit null sein kann, immer nullable per Fragezeichen.

   1:    OnAction?.Invoke();

Die Blazor Page beinhaltet die Component und wie vorher beim Button Click, die Referenz auf das zu erstellenden Code Schnipsel.

   1:  <Component OnAction="Action1"

Könnte wie folgt aussehen.

   1:  void Action1()
   2:  {
   3:          ding1 = "ding1";
   4:  }

Nehmen wir weiter an, Ding1 ist eine im HTML per @ding1 gebundene Variable. Man wird merken, das Ding aktualisiert sich nicht. Klappt erst, wenn man nach Zeile 3 ein StateHasChanged() einfügt und damit den Renderer anwirft.

Einer Action kann man ganz im Sinne von MouseEventargs auch von innen nach Aufrufer Argumente mitgeben. Die Variante mit Rückgabewert nennt sich Func. Der letzte Parameter ist der Out Wert.

   1:   [Parameter]
   2:   public Action OnAction { get; set; }
   3:   [Parameter]
   4:   public Action<string> OnAction2 { get; set; }
   5:   [Parameter]
   6:   public Func<int,int> OnFunc { get; set; } //in out

Blazor hat allerdings, wie Eingangs am Button Beispiel demonstriert, eine speziellen Typ Eventcallback. Mit oder ohne generische Parameter.

   1:  [Parameter]
   2:  public EventCallback<int> OnEventCallback { get; set; }

Die wichtigsten Unterschiede zwischen Action und Eventcallback auf einen Blick

  • Löst automatisch StateHasChanged aus
  • läut Async und erlaut Await aufrufe
  • erlaubt Rückgabe Task Objekt
  • Kann nicht null sein

Dabei muss der Code mit Event keine .razor Komponente sein. Auch C# Klassen lassen sich so mit einem Callback System ausstatten, wie man es in ViewModels durchaus benötigt.

Ein Invoke auf Component oder Klassenebene muss dann logischerweise auch asynchron ausgeführt werden.

   1:   OnEventCallback.InvokeAsync(currentCount);
Kommentare sind geschlossen