ASP.NET Core Blazor-Ereignisbehandlung

Hinweis

Dies ist nicht die neueste Version dieses Artikels. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Wichtig

Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.

Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

In diesem Artikel werden die Features zur Ereignisbehandlung von Blazor erläutert, einschließlich Ereignisargumenttypen, Ereignisrückrufe und die Verwaltung von Standardereignissen in Browsern.

Delegieren von Ereignishandlern

Angeben von Delegatereignishandlern im Razor-Komponentenmarkup mit @on{DOM EVENT}="{DELEGATE}"Razor-Syntax:

  • Der Platzhalter {DOM EVENT} ist ein DOM-Ereignis, (z. B. click).
  • Der Platzhalter {DELEGATE} ist der C#-Delegatereignishandler.

Für Ereignisbehandlung gilt Folgendes:

  • Asynchrone Delegatereignishandler, die ein Task-Element zurückgeben, werden unterstützt.
  • Delegatereignishandler lösen automatisch Rendering der Benutzeroberfläche aus, sodass StateHasChanged nicht manuell aufgerufen werden muss.
  • Ausnahmen werden protokolliert.

Der folgende Code

  • Ruft die UpdateHeading-Methode auf, wenn die Schaltfläche in der Benutzeroberfläche ausgewählt wird.
  • ruft die CheckChanged-Methode auf, wenn das Kontrollkästchen auf der Benutzeroberfläche geändert wird.

EventHandler1.razor:

@page "/event-handler-1"

<PageTitle>Event Handler 1</PageTitle>

<h1>Event Handler Example 1</h1>

<h2>@headingValue</h2>

<p>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

<p>
    <label>
        <input type="checkbox" @onchange="CheckChanged" />
        @checkedMessage
    </label>
</p>

@code {
    private string headingValue = "Initial heading";
    private string checkedMessage = "Not changed yet";

    private void UpdateHeading()
    {
        headingValue = $"New heading ({DateTime.Now})";
    }

    private void CheckChanged()
    {
        checkedMessage = $"Last changed at {DateTime.Now}";
    }
}

EventHandlerExample1.razor:

@page "/event-handler-1"

<h1>@headingValue</h1>

<p>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

<p>
    <label>
        <input type="checkbox" @onchange="CheckChanged" />
        @checkedMessage
    </label>
</p>

@code {
    private string headingValue = "Initial heading";
    private string checkedMessage = "Not changed yet";

    private void UpdateHeading()
    {
        headingValue = $"New heading ({DateTime.Now})";
    }

    private void CheckChanged()
    {
        checkedMessage = $"Last changed at {DateTime.Now}";
    }
}

EventHandlerExample1.razor:

@page "/event-handler-1"

<h1>@headingValue</h1>

<p>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

<p>
    <label>
        <input type="checkbox" @onchange="CheckChanged" />
        @checkedMessage
    </label>
</p>

@code {
    private string headingValue = "Initial heading";
    private string checkedMessage = "Not changed yet";

    private void UpdateHeading()
    {
        headingValue = $"New heading ({DateTime.Now})";
    }

    private void CheckChanged()
    {
        checkedMessage = $"Last changed at {DateTime.Now}";
    }
}

EventHandlerExample1.razor:

@page "/event-handler-1"

<h1>@headingValue</h1>

<p>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

<p>
    <label>
        <input type="checkbox" @onchange="CheckChanged" />
        @checkedMessage
    </label>
</p>

@code {
    private string headingValue = "Initial heading";
    private string checkedMessage = "Not changed yet";

    private void UpdateHeading()
    {
        headingValue = $"New heading ({DateTime.Now})";
    }

    private void CheckChanged()
    {
        checkedMessage = $"Last changed at {DateTime.Now}";
    }
}

EventHandlerExample1.razor:

@page "/event-handler-1"

<h1>@headingValue</h1>

<p>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

<p>
    <label>
        <input type="checkbox" @onchange="CheckChanged" />
        @checkedMessage
    </label>
</p>

@code {
    private string headingValue = "Initial heading";
    private string checkedMessage = "Not changed yet";

    private void UpdateHeading()
    {
        headingValue = $"New heading ({DateTime.Now})";
    }

    private void CheckChanged()
    {
        checkedMessage = $"Last changed at {DateTime.Now}";
    }
}

Im folgenden Beispiel gilt für UpdateHeading:

  • Wird asynchron aufgerufen, wenn die Schaltfläche ausgewählt wird.
  • Wartet zwei Sekunden, bevor die Überschrift aktualisiert wird.

EventHandler2.razor:

@page "/event-handler-2"

<PageTitle>Event Handler 2</PageTitle>

<h1>Event Handler Example 2</h1>

<h2>@headingValue</h2>

<p>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

@code {
    private string headingValue = "Initial heading";

    private async Task UpdateHeading()
    {
        await Task.Delay(2000);

        headingValue = $"New heading ({DateTime.Now})";
    }
}

EventHandlerExample2.razor:

@page "/event-handler-2"

<h1>@headingValue</h1>

<p>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

@code {
    private string headingValue = "Initial heading";

    private async Task UpdateHeading()
    {
        await Task.Delay(2000);

        headingValue = $"New heading ({DateTime.Now})";
    }
}

EventHandlerExample2.razor:

@page "/event-handler-2"

<h1>@headingValue</h1>

<p>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

@code {
    private string headingValue = "Initial heading";

    private async Task UpdateHeading()
    {
        await Task.Delay(2000);

        headingValue = $"New heading ({DateTime.Now})";
    }
}

EventHandlerExample2.razor:

@page "/event-handler-2"

<h1>@headingValue</h1>

<p>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

@code {
    private string headingValue = "Initial heading";

    private async Task UpdateHeading()
    {
        await Task.Delay(2000);

        headingValue = $"New heading ({DateTime.Now})";
    }
}

EventHandlerExample2.razor:

@page "/event-handler-2"

<h1>@headingValue</h1>

<p>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

@code {
    private string headingValue = "Initial heading";

    private async Task UpdateHeading()
    {
        await Task.Delay(2000);

        headingValue = $"New heading ({DateTime.Now})";
    }
}

Integrierte Ereignisargumente

Bei Ereignissen, die einen Ereignisargumenttyp unterstützen, ist die Angabe eines Ereignisparameters in der Definition der Ereignismethode nur erforderlich, wenn der Ereignistyp in der Methode verwendet wird. Im folgenden Beispiel wird MouseEventArgs in der ReportPointerLocation-Methode verwendet, um Meldungstext festzulegen, der die Mauskoordinaten meldet, wenn der Benutzer eine Schaltfläche in der Benutzeroberfläche auswählt.

EventHandler3.razor:

@page "/event-handler-3"

<PageTitle>Event Handler 3</PageTitle>

<h1>Event Handler Example 3</h1>

@for (var i = 0; i < 4; i++)
{
    <p>
        <button @onclick="ReportPointerLocation">
            Where's my mouse pointer for this button?
        </button>
    </p>
}

<p>@mousePointerMessage</p>

@code {
    private string? mousePointerMessage;

    private void ReportPointerLocation(MouseEventArgs e)
    {
        mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
    }
}

EventHandlerExample3.razor:

@page "/event-handler-example-3"

@for (var i = 0; i < 4; i++)
{
    <p>
        <button @onclick="ReportPointerLocation">
            Where's my mouse pointer for this button?
        </button>
    </p>
}

<p>@mousePointerMessage</p>

@code {
    private string? mousePointerMessage;

    private void ReportPointerLocation(MouseEventArgs e)
    {
        mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
    }
}

EventHandlerExample3.razor:

@page "/event-handler-example-3"

@for (var i = 0; i < 4; i++)
{
    <p>
        <button @onclick="ReportPointerLocation">
            Where's my mouse pointer for this button?
        </button>
    </p>
}

<p>@mousePointerMessage</p>

@code {
    private string? mousePointerMessage;

    private void ReportPointerLocation(MouseEventArgs e)
    {
        mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
    }
}

EventHandlerExample3.razor:

@page "/event-handler-example-3"

@for (var i = 0; i < 4; i++)
{
    <p>
        <button @onclick="ReportPointerLocation">
            Where's my mouse pointer for this button?
        </button>
    </p>
}

<p>@mousePointerMessage</p>

@code {
    private string mousePointerMessage;

    private void ReportPointerLocation(MouseEventArgs e)
    {
        mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
    }
}

EventHandlerExample3.razor:

@page "/event-handler-example-3"

@for (var i = 0; i < 4; i++)
{
    <p>
        <button @onclick="ReportPointerLocation">
            Where's my mouse pointer for this button?
        </button>
    </p>
}

<p>@mousePointerMessage</p>

@code {
    private string mousePointerMessage;

    private void ReportPointerLocation(MouseEventArgs e)
    {
        mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
    }
}

Die unterstützten EventArgs sind in der folgenden Tabelle aufgeführt.

event Klasse DOM-Hinweise
Zwischenablage ClipboardEventArgs
Ziehen DragEventArgs DataTransfer und DataTransferItem speichern gezogene Elementdaten.

Implementiert Drag & Drop in Blazor-Apps mit JS-Interop und der HTML-Drag & Drop-API.
Fehler ErrorEventArgs
event EventArgs EventHandlers enthält Attribute zum Konfigurieren der Zuordnungen zwischen Ereignisnamen und Ereignisargumenttypen.
Fokus FocusEventArgs Umfasst nicht die Unterstützung für relatedTarget.
Eingabe ChangeEventArgs
Tastatur KeyboardEventArgs
Maus MouseEventArgs
Mauszeiger PointerEventArgs
Mausrad WheelEventArgs
Fortschritt ProgressEventArgs
Touch TouchEventArgs TouchPoint stellt einen einzelnen Kontaktpunkt auf einem Gerät mit Berührungseingabe dar.

Weitere Informationen finden Sie in den folgenden Ressourcen:

Benutzerdefinierte Ereignisargumente

Blazor unterstützt benutzerdefinierte Ereignisargumente, die es Ihnen ermöglichen, beliebige Daten mit benutzerdefinierten Ereignissen an .NET-Ereignishandler zu übergeben.

Allgemeine Konfiguration

Benutzerdefinierte Ereignisse mit benutzerdefinierten Ereignisargumenten werden in der Regel mit den folgenden Schritten aktiviert.

Definieren Sie in JavaScript eine Funktion zum Erstellen des benutzerdefinierten Ereignisargumentobjekts aus dem Quellereignis:

function eventArgsCreator(event) { 
  return {
    customProperty1: 'any value for property 1',
    customProperty2: event.srcElement.id
  };
}

Der event-Parameter ist ein DOM-Ereignis (MDN-Dokumentation).

Registrieren Sie das benutzerdefinierte Ereignis mit dem vorherigen Handler in einem JavaScript-Initialisierer. Stellen Sie den entsprechenden Namen des Browser-Ereignisses an browserEventName bereit, das für das in diesem Abschnitt gezeigte Beispiel click ist für eine Schaltflächenauswahl auf der Benutzeroberfläche.

wwwroot/{PACKAGE ID/ASSEMBLY NAME}.lib.module.js (der Platzhalter {PACKAGE ID/ASSEMBLY NAME} ist die Paket-ID oder der Assemblyname der App):

Für eine Blazor-Web-App:

export function afterWebStarted(blazor) {
  blazor.registerCustomEventType('customevent', {
    browserEventName: 'click',
    createEventArgs: eventArgsCreator
  });
}

Für eine Blazor Server- oder Blazor WebAssembly-App:

export function afterStarted(blazor) {
  blazor.registerCustomEventType('customevent', {
    browserEventName: 'click',
    createEventArgs: eventArgsCreator
  });
}

Hinweis

Der Aufruf von registerCustomEventType wird nur ein Mal pro Ereignis in einem Skript ausgeführt.

Verwenden Sie für den Aufruf von registerCustomEventType den Parameter blazor (klein geschrieben b), der vom Blazor-Startereignis bereitgestellt wird. Die Registrierung ist zwar auch bei Verwendung des Objekts Blazor (mit großem B) gültig, aber die bevorzugte Vorgehensweise besteht darin, den Parameter zu verwenden.

Definieren Sie eine Klasse für die Ereignisargumente:

namespace BlazorSample.CustomEvents;

public class CustomEventArgs : EventArgs
{
    public string? CustomProperty1 {get; set;}
    public string? CustomProperty2 {get; set;}
}

Verbinden Sie das benutzerdefinierte Ereignis mit den Ereignisargumenten ein, indem Sie eine [EventHandler]-Attributanmerkung für das benutzerdefinierte Ereignis hinzufügen.

  • Damit der Compiler die Klasse [EventHandler] finden kann, muss sie in eine C#-Klassendatei (.cs) eingefügt werden, sodass sie eine normale Klasse auf oberster Ebene ist.
  • Markieren Sie die Klasse als public.
  • Die Klasse erfordert keine Member.
  • Die Klasse muss als EventHandlers bezeichnet werden, damit sie vom Razor-Compiler gefunden wird.
  • Fügen Sie die Klasse in einem Namespace ein, der für Ihre App spezifisch ist.
  • Importieren Sie den Namespace in die Razor-Komponente (.razor), in der das Ereignis verwendet wird.
using Microsoft.AspNetCore.Components;

namespace BlazorSample.CustomEvents;

[EventHandler("oncustomevent", typeof(CustomEventArgs),
    enableStopPropagation: true, enablePreventDefault: true)]
public static class EventHandlers
{
}

Registrieren Sie den Ereignishandler für mindestens ein HTML-Element. Greifen Sie auf die Daten zu, die von JavaScript in der Delegathandlermethode übergeben wurden:

@using BlazorSample.CustomEvents

<button id="buttonId" @oncustomevent="HandleCustomEvent">Handle</button>

@if (!string.IsNullOrEmpty(propVal1) && !string.IsNullOrEmpty(propVal2))
{
    <ul>
        <li>propVal1: @propVal1</li>
        <li>propVal2: @propVal2</li>
    </ul>
}

@code
{
    private string? propVal1;
    private string? propVal2;

    private void HandleCustomEvent(CustomEventArgs eventArgs)
    {
        propVal1 = eventArgs.CustomProperty1;
        propVal2 = eventArgs.CustomProperty2;
    }
}

Wenn das @oncustomevent-Attribut von IntelliSense nicht erkannt wird, stellen Sie sicher, dass die Komponente oder die _Imports.razor-Datei eine @using-Anweisung für den Namespace enthält, der die EventHandler-Klasse enthält.

Wenn das benutzerdefinierte Ereignis im DOM ausgelöst wird, wird der Ereignishandler mit den Daten aufgerufen, die von JavaScript übergeben werden.

Wenn Sie versuchen, ein benutzerdefiniertes Ereignis auszulösen, muss bubbles aktiviert werden, indem der zugehörige Wert auf true festgelegt wird. Andernfalls erreicht das Ereignis nicht den Blazor-Handler für Verarbeitung in die benutzerdefinierte C#-[EventHandler]-Attributklasse. Weitere Informationen finden Sie unter MDN-Webdokumentation: Event Bubbling.

Beispiel für Ereignis für benutzerdefiniertes Einfügen aus der Zwischenablage

Im folgenden Beispiel wird ein benutzerdefiniertes Einfügeereignis aus der Zwischenablage empfangen, das die Uhrzeit des Einfügens und den eingefügten Text des Benutzers enthält.

Deklarieren Sie einen benutzerdefinierten Namen (oncustompaste) für das Ereignis und eine .NET-Klasse (CustomPasteEventArgs), die die Ereignisargumente für dieses Ereignis enthält:

CustomEvents.cs:

using Microsoft.AspNetCore.Components;

namespace BlazorSample.CustomEvents;

[EventHandler("oncustompaste", typeof(CustomPasteEventArgs), 
    enableStopPropagation: true, enablePreventDefault: true)]
public static class EventHandlers
{
}

public class CustomPasteEventArgs : EventArgs
{
    public DateTime EventTimestamp { get; set; }
    public string? PastedData { get; set; }
}

Fügen Sie JavaScript-Code hinzu, um Daten für die Unterklasse EventArgs mit dem vorherigen Handler in einem JavaScript-Initialisierer zu liefern. Das folgende Beispiel behandelt nur das Einfügen von Text, aber Sie könnten beliebige JavaScript-APIs verwenden, um Benutzer zu berücksichtigen, die andere Datentypen einfügen, z. B. Bilder.

wwwroot/{PACKAGE ID/ASSEMBLY NAME}.lib.module.js:

Für eine Blazor-Web-App:

export function afterWebStarted(blazor) {
  blazor.registerCustomEventType('custompaste', {
    browserEventName: 'paste',
    createEventArgs: event => {
      return {
        eventTimestamp: new Date(),
        pastedData: event.clipboardData.getData('text')
      };
    }
  });
}

Für eine Blazor Server- oder Blazor WebAssembly-App:

export function afterStarted(blazor) {
  blazor.registerCustomEventType('custompaste', {
    browserEventName: 'paste',
    createEventArgs: event => {
      return {
        eventTimestamp: new Date(),
        pastedData: event.clipboardData.getData('text')
      };
    }
  });
}

Im vorherigen Beispiel steht der Platzhalter {PACKAGE ID/ASSEMBLY NAME} des Dateinamens für die Paket-ID oder den Assemblynamen der App.

Hinweis

Verwenden Sie für den Aufruf von registerCustomEventType den Parameter blazor (klein geschrieben b), der vom Blazor-Startereignis bereitgestellt wird. Die Registrierung ist zwar auch bei Verwendung des Objekts Blazor (mit großem B) gültig, aber die bevorzugte Vorgehensweise besteht darin, den Parameter zu verwenden.

Der Code oben weist den Browser an, die folgenden Aktionen auszuführen, wenn ein natives paste-Ereignis auftritt:

  • Auslösen eines custompaste-Ereignisses.
  • Bereitstellen der Ereignisargumentdaten mithilfe der angegebenen benutzerdefinierten Logik:

Ereignisnamenskonventionen unterscheiden sich in .NET und JavaScript:

  • In .NET haben Ereignisnamen das Präfix on.
  • In JavaScript haben Ereignisnamen kein Präfix.

Fügen Sie in einer Razor-Komponente den benutzerdefinierten Handler an ein Element an.

CustomPasteArguments.razor:

@page "/custom-paste-arguments"
@using BlazorSample.CustomEvents

<label>
    Try pasting into the following text box:
    <input @oncustompaste="HandleCustomPaste" />
</label>

<p>
    @message
</p>

@code {
    private string? message;

    private void HandleCustomPaste(CustomPasteEventArgs eventArgs)
    {
        message = $"At {eventArgs.EventTimestamp.ToShortTimeString()}, " +
            $"you pasted: {eventArgs.PastedData}";
    }
}

Lambdaausdrücke

Lambdaausdrücke werden als Delegatereignishandler unterstützt.

EventHandler4.razor:

@page "/event-handler-4"

<PageTitle>Event Handler 4</PageTitle>

<h1>Event Handler Example 4</h1>

<h2>@heading</h2>

<p>
    <button @onclick="@(e => heading = "New heading!!!")">
        Update heading
    </button>
</p>

@code {
    private string heading = "Initial heading";
}

EventHandlerExample4.razor:

@page "/event-handler-example-4"

<h1>@heading</h1>

<p>
    <button @onclick="@(e => heading = "New heading!!!")">
        Update heading
    </button>
</p>

@code {
    private string heading = "Initial heading";
}

EventHandlerExample4.razor:

@page "/event-handler-example-4"

<h1>@heading</h1>

<p>
    <button @onclick="@(e => heading = "New heading!!!")">
        Update heading
    </button>
</p>

@code {
    private string heading = "Initial heading";
}

EventHandlerExample4.razor:

@page "/event-handler-example-4"

<h1>@heading</h1>

<p>
    <button @onclick="@(e => heading = "New heading!!!")">
        Update heading
    </button>
</p>

@code {
    private string heading = "Initial heading";
}

EventHandlerExample4.razor:

@page "/event-handler-example-4"

<h1>@heading</h1>

<p>
    <button @onclick="@(e => heading = "New heading!!!")">
        Update heading
    </button>
</p>

@code {
    private string heading = "Initial heading";
}

Es ist häufig praktisch, zusätzliche Werte mit C#-Methodenparametern hinzuzufügen, z. B. bei der Iteration über eine Reihe von Elementen. Im folgenden Beispiel werden drei Schaltflächen erstellt, von denen jede UpdateHeading aufruft und die folgenden Daten übergibt:

  • Ein Ereignisargument (MouseEventArgs) in e.
  • Die Schaltflächennummer in buttonNumber.

EventHandler5.razor:

@page "/event-handler-5"

<PageTitle>Event Handler 5</PageTitle>

<h1>Event Handler Example 5</h1>

<h2>@heading</h2>

@for (var i = 1; i < 4; i++)
{
    var buttonNumber = i;

    <p>
        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">
            Button #@i
        </button>
    </p>
}

@code {
    private string heading = "Select a button to learn its position";

    private void UpdateHeading(MouseEventArgs e, int buttonNumber)
    {
        heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
    }
}

EventHandlerExample5.razor:

@page "/event-handler-example-5"

<h1>@heading</h1>

@for (var i = 1; i < 4; i++)
{
    var buttonNumber = i;

    <p>
        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">
            Button #@i
        </button>
    </p>
}

@code {
    private string heading = "Select a button to learn its position";

    private void UpdateHeading(MouseEventArgs e, int buttonNumber)
    {
        heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
    }
}

EventHandlerExample5.razor:

@page "/event-handler-example-5"

<h1>@heading</h1>

@for (var i = 1; i < 4; i++)
{
    var buttonNumber = i;

    <p>
        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">
            Button #@i
        </button>
    </p>
}

@code {
    private string heading = "Select a button to learn its position";

    private void UpdateHeading(MouseEventArgs e, int buttonNumber)
    {
        heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
    }
}

EventHandlerExample5.razor:

@page "/event-handler-example-5"

<h1>@heading</h1>

@for (var i = 1; i < 4; i++)
{
    var buttonNumber = i;

    <p>
        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">
            Button #@i
        </button>
    </p>
}

@code {
    private string heading = "Select a button to learn its position";

    private void UpdateHeading(MouseEventArgs e, int buttonNumber)
    {
        heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
    }
}

EventHandlerExample5.razor:

@page "/event-handler-example-5"

<h1>@heading</h1>

@for (var i = 1; i < 4; i++)
{
    var buttonNumber = i;

    <p>
        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">
            Button #@i
        </button>
    </p>
}

@code {
    private string heading = "Select a button to learn its position";

    private void UpdateHeading(MouseEventArgs e, int buttonNumber)
    {
        heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
    }
}

Das Erstellen einer hohen Anzahl von Ereignisdelegaten in einer Schleife kann zu einer schlechten Renderingleistung führen. Weitere Informationen finden Sie unter Bewährte Methoden für die Leistung von Blazor in ASP.NET Core.

Verwenden Sie die direkte Verwendung einer Schleifenvariablen in einem Lambdaausdruck wie i im vorangehenden for-Schleifenbeispiel. Ansonsten wird dieselbe Variable von allen Lambdaausdrücken verwendet, sodass der gleiche Wert in allen Lambdaausdrücken verwendet wird. Erfassen Sie den Wert der Variablen in einer lokalen Variablen. Im vorherigen Beispiel:

  • Die Schleifenvariable i wird buttonNumber zugewiesen.
  • buttonNumber wird im Lambdaausdruck verwendet.

Verwenden Sie alternativ eine foreach Schleife mit Enumerable.Range, welche nicht vom vorherigen Problem betroffen ist:

@foreach (var buttonNumber in Enumerable.Range(1,3))
{
    <p>
        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">
            Button #@buttonNumber
        </button>
    </p>
}

EventCallback

Ein häufiges Szenario mit geschachtelten Komponenten ist die Ausführung einer Methode in einer übergeordneten Komponente, wenn ein Ereignis in einer untergeordneten Komponente auftritt. Das ein onclick-Ereignis in der untergeordneten Komponente auftritt, ist ein gängiger Anwendungsfall. Um Ereignisse komponentenübergreifend darzustellen, verwenden Sie ein EventCallback. Eine übergeordnete Komponente kann dem EventCallback einer untergeordneten Komponente eine Rückrufmethode zuweisen.

Die folgende Child-Komponente zeigt, wie der onclick-Handler einer Schaltfläche so eingerichtet wird, dass er einen EventCallback-Delegaten von der ParentComponent des Beispiels empfängt. EventCallback ist mit MouseEventArgs typisiert, was für ein onclick-Ereignis von einem Peripheriegerät angemessen ist.

Child.razor:

<p>
    <button @onclick="OnClickCallback">
        Trigger a Parent component method
    </button>
</p>

@code {
    [Parameter]
    public string? Title { get; set; }

    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    [Parameter]
    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<p>
    <button @onclick="OnClickCallback">
        Trigger a Parent component method
    </button>
</p>

@code {
    [Parameter]
    public string? Title { get; set; }

    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    [Parameter]
    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<p>
    <button @onclick="OnClickCallback">
        Trigger a Parent component method
    </button>
</p>

@code {
    [Parameter]
    public string? Title { get; set; }

    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    [Parameter]
    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<p>
    <button @onclick="OnClickCallback">
        Trigger a Parent component method
    </button>
</p>

@code {
    [Parameter]
    public string Title { get; set; }

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    [Parameter]
    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<p>
    <button @onclick="OnClickCallback">
        Trigger a Parent component method
    </button>
</p>

@code {
    [Parameter]
    public string Title { get; set; }

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    [Parameter]
    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}

Die Parent-Komponente legt EventCallback<TValue> (OnClickCallback) des untergeordneten Elements auf seine ShowMessage-Methode fest.

ParentChild.razor:

@page "/parent-child"

<PageTitle>Parent Child</PageTitle>

<h1>Parent Child Example</h1>

<Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">
    Content of the child component is supplied by the parent component.
</Child>

<p>@message</p>

@code {
    private string? message;

    private void ShowMessage(MouseEventArgs e)
    {
        message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
    }
}

Parent.razor:

@page "/parent"

<h1>Parent-child example</h1>

<Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">
    Content of the child component is supplied by the parent component.
</Child>

<p>@message</p>

@code {
    private string? message;

    private void ShowMessage(MouseEventArgs e)
    {
        message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
    }
}

Parent.razor:

@page "/parent"

<h1>Parent-child example</h1>

<Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">
    Content of the child component is supplied by the parent component.
</Child>

<p>@message</p>

@code {
    private string? message;

    private void ShowMessage(MouseEventArgs e)
    {
        message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
    }
}

Parent.razor:

@page "/parent"

<h1>Parent-child example</h1>

<Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">
    Content of the child component is supplied by the parent component.
</Child>

<p>@message</p>

@code {
    private string message;

    private void ShowMessage(MouseEventArgs e)
    {
        message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
    }
}

Parent.razor:

@page "/parent"

<h1>Parent-child example</h1>

<Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">
    Content of the child component is supplied by the parent component.
</Child>

<p>@message</p>

@code {
    private string message;

    private void ShowMessage(MouseEventArgs e)
    {
        message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
    }
}

Wenn die Schaltfläche in der ChildComponent ausgewählt ist:

  • Die ShowMessage-Methode der Parent-Komponente wird aufgerufen. message wird aktualisiert und in der Parent-Komponente angezeigt.
  • Ein Aufruf von StateHasChanged ist in der Methode des Rückrufs (ShowMessage) nicht erforderlich. StateHasChanged wird automatisch aufgerufen, um die Parent-Komponente zu rendern, so wie Ereignisse untergeordneter Elemente das Rendern von Komponenten in Ereignishandlern auslösen, die innerhalb des untergeordneten Elements ausgeführt werden. Weitere Informationen finden Sie unter Rendering von Razor-Komponenten in ASP.NET Core.

Verwenden Sie EventCallback und EventCallback<TValue> für die Ereignisbehandlung und die Bindung von Komponentenparametern.

Bevorzugen Sie das stark typisierte EventCallback<TValue> gegenüber dem EventCallback. EventCallback<TValue> bietet erweitertes Fehlerfeedback, das bei der Benutzung eines unangemessenen Typs verwendet wird und Benutzer der Komponente zur korrekten Implementierung führt. Ähnlich wie bei anderen UI-Ereignishandlern ist die Angabe des Ereignisparameters optional. Verwenden Sie EventCallback, wenn kein Wert an den Rückruf übergeben wurde.

EventCallback und EventCallback<TValue> gestatten asynchrone Delegate. EventCallback ist schwach typisiert und erlaubt das Übergeben von Argumenten eines beliebigen Typs in InvokeAsync(Object). EventCallback<TValue> ist stark typisiert und erfordert das Übergeben eines T-Arguments in InvokeAsync(T), das TValue zugewiesen werden kann.

Rufen Sie ein EventCallback oder EventCallback<TValue> mit InvokeAsync auf, und warten Sie auf das Task:

await OnClickCallback.InvokeAsync({ARGUMENT});

Im vorherigen Beispiel ist der {ARGUMENT}-Platzhalter ein optionales Argument.

Im folgenden hierarchischen Beispiel wird die Technik veranschaulicht.

Child2.razor:

<h3>Child2 Component</h3>

<button @onclick="TriggerEvent">Click Me</button>

@code {
    [Parameter]
    public EventCallback<string> OnClickCallback { get; set; }

    private async Task TriggerEvent()
    {
        await OnClickCallback.InvokeAsync("Blaze It!");
    }
}

ParentChild2.razor:

@page "/parent-child-2"

<PageTitle>Parent Child 2</PageTitle>

<h1>Parent Child 2 Example</h1>

<div>
    <Child2 OnClickCallback="(value) => { message1 = value; }" />
    @message1
</div>

<div>
    <Child2 OnClickCallback=
        "async (value) => { await Task.Delay(2000); message2 = value; }" /> 
    @message2
</div>

@code {
    private string message1 = string.Empty;
    private string message2 = string.Empty;
}

Das zweite Vorkommen der Child2-Komponente veranschaulicht einen asynchronen Rückruf, und der neue message2-Wert wird zugewiesen und mit einer Verzögerung von zwei Sekunden gerendert.

Verhindern von Standardaktionen

Verwenden Sie das Anweisungsattribut @on{DOM EVENT}:preventDefault, um die Standardaktion für ein Ereignis zu verhindern, bei dem der Platzhalter {DOM EVENT} ein DOM-Ereignis ist.

Wenn ein Schlüssel auf einem Eingabegerät ausgewählt wird und der Elementfokus auf einem Textfeld liegt, zeigt ein Browser normalerweise das Zeichen des Schlüssels in dem Textfeld an. Im folgenden Beispiel wird das Standardverhalten durch die Angabe des Direktivenattributs @onkeydown:preventDefault verhindert. Wenn sich der Fokus auf dem <input>-Element befindet, wird der Zähler mit der Tastenkombination UMSCHALT++ inkrementiert. Das Zeichen + wird nicht dem Wert des <input>-Elements zugewiesen. Weitere Informationen zu keydown finden Sie unter MDN Web Docs: Document: keydown-Ereignis.

EventHandler6.razor:

@page "/event-handler-6"

<PageTitle>Event Handler 6</PageTitle>

<h1>Event Handler Example 6</h1>

<p>For this example, give the <code><input></code> focus.</p>

<p>
    <label>
        Count of '+' key presses: 
        <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
    </label>
</p>

@code {
    private int count = 0;

    private void KeyHandler(KeyboardEventArgs e)
    {
        if (e.Key == "+")
        {
            count++;
        }
    }
}

EventHandlerExample6.razor:

@page "/event-handler-example-6"

<p>
    <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</p>

@code {
    private int count = 0;

    private void KeyHandler(KeyboardEventArgs e)
    {
        if (e.Key == "+")
        {
            count++;
        }
    }
}

EventHandlerExample6.razor:

@page "/event-handler-example-6"

<p>
    <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</p>

@code {
    private int count = 0;

    private void KeyHandler(KeyboardEventArgs e)
    {
        if (e.Key == "+")
        {
            count++;
        }
    }
}

EventHandlerExample6.razor:

@page "/event-handler-example-6"

<p>
    <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</p>

@code {
    private int count = 0;

    private void KeyHandler(KeyboardEventArgs e)
    {
        if (e.Key == "+")
        {
            count++;
        }
    }
}

EventHandlerExample6.razor:

@page "/event-handler-example-6"

<p>
    <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</p>

@code {
    private int count = 0;

    private void KeyHandler(KeyboardEventArgs e)
    {
        if (e.Key == "+")
        {
            count++;
        }
    }
}

Die Angabe des Attributs @on{DOM EVENT}:preventDefault ohne Wert ist gleichbedeutend mit @on{DOM EVENT}:preventDefault="true".

Ein Ausdruck ist ebenfalls ein zulässiger Wert des Attributs. Im folgenden Beispiel ist shouldPreventDefault ein bool-Feld, das entweder auf true oder false festgelegt ist:

<input @onkeydown:preventDefault="shouldPreventDefault" />

...

@code {
    private bool shouldPreventDefault = true;
}

Beenden der Ereignisweitergabe

Verwenden Sie das Anweisungsattribut @on{DOM EVENT}:stopPropagation, um die Ereignispropagierung im Blazor-Bereich zu beenden. {DOM EVENT} ist ein Platzhalter für ein DOM-Ereignis.

Die Wirkung des Anweisungsattributs stopPropagation ist auf den Blazor-Bereich beschränkt und gilt nicht für das HTML-DOM. Ereignisse müssen an den Stamm des HTML-DOM weitergegeben werden, bevor Blazor auf sie reagieren kann. Um die Weitergabe von HTML-DOM-Ereignissen zu verhindern, sollten Sie den folgenden Ansatz befolgen:

Im folgenden Beispiel wird die Weitergabe von Klickereignissen vom zweiten untergeordneten <div>-Element an das übergeordnete <div>-Element verhindert, wenn das Kontrollkästchen aktiviert wird. Da weitergegebene „click“-Ereignisse normalerweise die Methode OnSelectParentDiv auslösen, führt das Auswählen des zweiten untergeordneten <div>-Elements dazu, dass die übergeordnete <div>-Meldung angezeigt wird, es sei denn, das Kontrollkästchen ist aktiviert.

EventHandler7.razor:

@page "/event-handler-7"

<PageTitle>Event Handler 7</PageTitle>

<h1>Event Handler Example 7</h1>

<div>
    <b>stopPropagation</b>: @stopPropagation
</div>

<div>
    <button @onclick="StopPropagation">
        Stop Propagation (stopPropagation = true)
    </button>
    <button @onclick="EnablePropagation">
        Enable Propagation (stopPropagation = false)
    </button>
</div>

<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
    <h3>Parent div</h3>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
        Child div that never stops propagation to the parent div when 
        selected.
    </div>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv" 
            @onclick:stopPropagation="stopPropagation">
        Child div that stops propagation when selected if 
        <b>stopPropagation</b> is <b>true</b>.
    </div>
</div>

<p>
    @message
</p>

@code {
    private bool stopPropagation = false;
    private string? message;

    private void StopPropagation() => stopPropagation = true;

    private void EnablePropagation() => stopPropagation = false;

    private void OnSelectParentDiv() =>
        message = $"The parent div was selected. {DateTime.Now}";

    private void OnSelectChildDiv() =>
        message = $"The child div was selected. {DateTime.Now}";
}

EventHandlerExample7.razor:

@page "/event-handler-example-7"

<div>
    <b>stopPropagation</b>: @stopPropagation
</div>

<div>
    <button @onclick="StopPropagation">
        Stop Propagation (stopPropagation = true)
    </button>
    <button @onclick="EnablePropagation">
        Enable Propagation (stopPropagation = false)
    </button>
</div>

<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
    <h3>Parent div</h3>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
        Child div that never stops propagation to the parent div when 
        selected.
    </div>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv" 
            @onclick:stopPropagation="stopPropagation">
        Child div that stops propagation when selected if 
        <b>stopPropagation</b> is <b>true</b>.
    </div>
</div>

<p>
    @message
</p>

@code {
    private bool stopPropagation = false;
    private string? message;

    private void StopPropagation() => stopPropagation = true;

    private void EnablePropagation() => stopPropagation = false;

    private void OnSelectParentDiv() =>
        message = $"The parent div was selected. {DateTime.Now}";

    private void OnSelectChildDiv() =>
        message = $"The child div was selected. {DateTime.Now}";
}

EventHandlerExample7.razor:

@page "/event-handler-example-7"

<div>
    <b>stopPropagation</b>: @stopPropagation
</div>

<div>
    <button @onclick="StopPropagation">
        Stop Propagation (stopPropagation = true)
    </button>
    <button @onclick="EnablePropagation">
        Enable Propagation (stopPropagation = false)
    </button>
</div>

<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
    <h3>Parent div</h3>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
        Child div that never stops propagation to the parent div when 
        selected.
    </div>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv" 
            @onclick:stopPropagation="stopPropagation">
        Child div that stops propagation when selected if 
        <b>stopPropagation</b> is <b>true</b>.
    </div>
</div>

<p>
    @message
</p>

@code {
    private bool stopPropagation = false;
    private string? message;

    private void StopPropagation() => stopPropagation = true;

    private void EnablePropagation() => stopPropagation = false;

    private void OnSelectParentDiv() =>
        message = $"The parent div was selected. {DateTime.Now}";

    private void OnSelectChildDiv() =>
        message = $"The child div was selected. {DateTime.Now}";
}

EventHandlerExample7.razor:

@page "/event-handler-example-7"

<div>
    <b>stopPropagation</b>: @stopPropagation
</div>

<div>
    <button @onclick="StopPropagation">
        Stop Propagation (stopPropagation = true)
    </button>
    <button @onclick="EnablePropagation">
        Enable Propagation (stopPropagation = false)
    </button>
</div>

<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
    <h3>Parent div</h3>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
        Child div that never stops propagation to the parent div when 
        selected.
    </div>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv" 
            @onclick:stopPropagation="stopPropagation">
        Child div that stops propagation when selected if 
        <b>stopPropagation</b> is <b>true</b>.
    </div>
</div>

<p>
    @message
</p>

@code {
    private bool stopPropagation = false;
    private string message;

    private void StopPropagation() => stopPropagation = true;

    private void EnablePropagation() => stopPropagation = false;

    private void OnSelectParentDiv() =>
        message = $"The parent div was selected. {DateTime.Now}";

    private void OnSelectChildDiv() =>
        message = $"The child div was selected. {DateTime.Now}";
}

EventHandlerExample7.razor:

@page "/event-handler-example-7"

<div>
    <b>stopPropagation</b>: @stopPropagation
</div>

<div>
    <button @onclick="StopPropagation">
        Stop Propagation (stopPropagation = true)
    </button>
    <button @onclick="EnablePropagation">
        Enable Propagation (stopPropagation = false)
    </button>
</div>

<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
    <h3>Parent div</h3>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
        Child div that never stops propagation to the parent div when 
        selected.
    </div>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv" 
            @onclick:stopPropagation="stopPropagation">
        Child div that stops propagation when selected if 
        <b>stopPropagation</b> is <b>true</b>.
    </div>
</div>

<p>
    @message
</p>

@code {
    private bool stopPropagation = false;
    private string message;

    private void StopPropagation() => stopPropagation = true;

    private void EnablePropagation() => stopPropagation = false;

    private void OnSelectParentDiv() =>
        message = $"The parent div was selected. {DateTime.Now}";

    private void OnSelectChildDiv() =>
        message = $"The child div was selected. {DateTime.Now}";
}

Fokussieren eines Elements

Rufen Sie FocusAsync für einen Elementverweis auf, um den Fokus auf einem Element im Code zu platzieren. Wählen Sie im folgenden Beispiel die Schaltfläche aus, um den Fokus auf dem <input>-Element zu platzieren.

EventHandler8.razor:

@page "/event-handler-8"

<PageTitle>Event Handler 8</PageTitle>

<h1>Event Handler Example 8</h1>

<p>Select the button to give the <code><input></code> focus.</p>

<p>
    <label>
        Input: 
        <input @ref="exampleInput" />
    </label>
    
</p>

<button @onclick="ChangeFocus">
    Focus the Input Element
</button>

@code {
    private ElementReference exampleInput;

    private async Task ChangeFocus()
    {
        await exampleInput.FocusAsync();
    }
}

EventHandlerExample8.razor:

@page "/event-handler-example-8"

<p>
    <input @ref="exampleInput" />
</p>

<button @onclick="ChangeFocus">
    Focus the Input Element
</button>

@code {
    private ElementReference exampleInput;

    private async Task ChangeFocus()
    {
        await exampleInput.FocusAsync();
    }
}

EventHandlerExample8.razor:

@page "/event-handler-example-8"

<p>
    <input @ref="exampleInput" />
</p>

<button @onclick="ChangeFocus">
    Focus the Input Element
</button>

@code {
    private ElementReference exampleInput;

    private async Task ChangeFocus()
    {
        await exampleInput.FocusAsync();
    }
}