Gestion des événements ASP.NET Core Blazor

Remarque

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.

Important

Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.

Pour la version actuelle, consultez la version .NET 8 de cet article.

Cet article explique les fonctionnalités de gestion des événements de Blazor, notamment les types d’arguments d’événement, les rappels d’événements et la gestion des événements de navigateur par défaut.

Déléguer des gestionnaires d’événements

Spécifiez les gestionnaires d’événements délégués dans le balisage de composant Razor avec la syntaxe @on{DOM EVENT}="{DELEGATE}"Razor :

  • L’espace réservé {DOM EVENT} est un événement DOM (par exemple, click).
  • L’espace réservé {DELEGATE} est le gestionnaire d’événements délégué C#.

Pour la gestion des événements :

  • Les gestionnaires d’événements délégués asynchrones qui retournent Task sont pris en charge.
  • Les gestionnaires d’événements délégués déclenchent automatiquement un rendu d’interface utilisateur. Il n’est donc pas nécessaire d’appeler manuellement StateHasChanged.
  • Les exceptions sont consignées.

L'exemple de code suivant :

  • Appelle la méthode UpdateHeading lorsque le bouton est sélectionné dans l’interface utilisateur.
  • Appelle la méthode CheckChanged lorsque la case à cocher est modifiée dans l’interface utilisateur.

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

Dans l’exemple suivant, UpdateHeading :

  • Est appelé de manière asynchrone lorsque le bouton est sélectionné.
  • Attend deux secondes avant de mettre à jour le titre.

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

Arguments d’événement intégrés

Pour les événements qui prennent en charge un type d’argument d’événement, la spécification d’un paramètre d’événement dans la définition de méthode d’événement n’est nécessaire que si le type d’événement est utilisé dans la méthode. Dans l’exemple suivant, MouseEventArgs est utilisé dans la méthode ReportPointerLocation pour définir le texte du message qui signale les coordonnées de la souris lorsque l’utilisateur sélectionne un bouton dans l’interface utilisateur.

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

Les EventArgs pris en charge sont indiqués dans le tableau suivant.

événement Classe Notes DOM
Presse-papiers ClipboardEventArgs
Glisser DragEventArgs DataTransfer et DataTransferItem contiennent les données de l’élément déplacé.

Implémentez le glisser-déplacer dans les applications Blazor à l’aide de l’interopérabilité JS avec l’API glisser-déplacer HTML.
Error ErrorEventArgs
événement EventArgs EventHandlers contient des attributs pour configurer les mappages entre les noms d’événements et les types d’arguments d’événement.
Focus FocusEventArgs N’inclut pas la prise en charge de relatedTarget.
Entrée ChangeEventArgs
Clavier KeyboardEventArgs
Souris MouseEventArgs
Pointeur de souris PointerEventArgs
Roulette de la souris WheelEventArgs
Progression ProgressEventArgs
Entrées tactiles TouchEventArgs TouchPoint représente un point de contact unique sur un appareil tactile.

Pour plus d'informations, reportez-vous aux ressources suivantes :

Arguments d’événement personnalisés

Blazor prend en charge les arguments d’événements personnalisés, ce qui vous permet de transmettre des données arbitraires aux gestionnaires d’événements .NET avec des événements personnalisés.

Configuration générale

Les événements personnalisés avec des arguments d’événement personnalisés sont généralement activés en procédant comme suit.

En JavaScript, définissez une fonction pour générer l’objet d’argument d’événement personnalisé à partir de l’événement source :

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

Le event paramètre est un événement DOM (documentation MDN).

Inscrivez l’événement personnalisé avec le gestionnaire précédent dans un initialiseur JavaScript. Indiquez le nom d’événement de navigateur approprié à browserEventName, qui, pour l’exemple indiqué dans cette section, correspond à une sélection de bouton click dans l’interface utilisateur.

wwwroot/{PACKAGE ID/ASSEMBLY NAME}.lib.module.js (l’{PACKAGE ID/ASSEMBLY NAME}espace réservé est l’ID du package ou le nom de l’assembly de l’application) :

Pour une application web Blazor :

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

Pour une application Blazor Server ou Blazor WebAssembly :

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

Remarque

L’appel à registerCustomEventType n’est effectué dans un script qu’une seule fois par événement.

Pour l’appel à registerCustomEventType, utilisez le paramètre blazor (b (en) minuscules) fourni par l’événement de démarrage Blazor. Bien que l’inscription soit valide lors de l’utilisation de l’objet Blazor (B majuscule), l’approche recommandée consiste à utiliser le paramètre.

Définissez une classe pour les arguments d’événement :

namespace BlazorSample.CustomEvents;

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

Reliez l’événement personnalisé avec les arguments de l’événement en ajoutant une annotation d’attribut [EventHandler] pour l’événement personnalisé :

  • Pour que le compilateur recherche la classe [EventHandler], celle-ci doit être placée dans un fichier de classe C# (.cs), ce qui en fait une classe de niveau supérieur normale.
  • Marquez la classe comme public.
  • La classe ne nécessite pas de membres.
  • La classe doit être appelée « EventHandlers » pour être trouvée par le compilateur Razor.
  • Placez la classe sous un espace de noms spécifique à votre application.
  • Importez l’espace de noms dans le composant Razor (.razor) où l’événement est utilisé.
using Microsoft.AspNetCore.Components;

namespace BlazorSample.CustomEvents;

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

Inscrivez le gestionnaire d’événements sur un ou plusieurs éléments HTML. Accédez aux données qui ont été transmises à partir de JavaScript dans la méthode de gestionnaire de délégués :

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

Si l’attribut @oncustomevent n’est pas reconnu par IntelliSense, vérifiez que le composant ou le fichier _Imports.razor contient une instruction @using pour l’espace de noms contenant la classe EventHandler.

Chaque fois que l’événement personnalisé est déclenché sur le DOM, le gestionnaire d’événements est appelé avec les données transmises à partir du JavaScript.

Si vous tentez de déclencher un événement personnalisé, bubbles doit être activé en définissant sa valeur sur true. Sinon, l’événement n’atteint pas le gestionnaire Blazor pour le traitement dans la classe d’attributs [EventHandler] personnalisée de C#. Pour plus d’informations, consultez Documentation web MDN : Propagation des événements.

Exemple d’événement de collage de presse-papiers personnalisé

L’exemple suivant reçoit un événement de collage de presse-papiers personnalisé qui inclut l’heure du collage et le texte collé de l’utilisateur.

Déclarez un nom personnalisé (oncustompaste) pour l’événement et une classe .NET (CustomPasteEventArgs) pour contenir les arguments de l’événement pour cet événement :

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

Ajoutez du code JavaScript pour fournir des données pour la sous-classe EventArgs avec le gestionnaire précédent dans un initialiseur JavaScript. L’exemple suivant gère uniquement le collage de texte, mais vous pouvez utiliser des API JavaScript arbitraires pour traiter les utilisateurs collant d’autres types de données, comme des images.

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

Pour une application web Blazor :

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

Pour une application Blazor Server ou Blazor WebAssembly :

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

Dans l’exemple précédent, l’espace réservé {PACKAGE ID/ASSEMBLY NAME} du nom de fichier représente l’ID de package ou le nom d’assembly de l’application.

Remarque

Pour l’appel à registerCustomEventType, utilisez le paramètre blazor (b (en) minuscules) fourni par l’événement de démarrage Blazor. Bien que l’inscription soit valide lors de l’utilisation de l’objet Blazor (B majuscule), l’approche recommandée consiste à utiliser le paramètre.

Le code précédent indique au navigateur que lorsqu’un événement natif paste se produit, il doit :

  • Déclencher un événement custompaste.
  • Fournir les données des arguments d’événement à l’aide de la logique personnalisée indiquée :

Les conventions de nom d’événement diffèrent entre .NET et JavaScript :

  • Dans .NET, les noms d’événement sont précédés de « on ».
  • En JavaScript, les noms d’événement n’ont pas de préfixe.

Dans un composant Razor, attachez le gestionnaire personnalisé à un élément.

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

Expressions lambda

Les expressions lambda sont prises en charge en tant que gestionnaire d’événements délégués.

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

Il est souvent pratique de fermer avec des valeurs supplémentaires à l’aide de paramètres de méthode C#, par exemple lors de l’itération sur un ensemble d’éléments. L’exemple suivant crée trois boutons ; chacun d’entre eux appelle UpdateHeading et transmet les données suivantes :

  • Argument d’événement (MouseEventArgs) dans e.
  • Numéro de bouton dans 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}";
    }
}

La création d’un grand nombre de délégués d’événements dans une boucle peut entraîner des performances de rendu médiocres. Pour plus d’informations, consultez Bonnes pratiques relatives aux performances d’ASP.NET Core Blazor.

Évitez d’utiliser une variable de boucle directement dans une expression lambda, comme i dans l’exemple de boucle for précédent. Sinon, la même variable est utilisée par toutes les expressions lambda, ce qui entraîne l’utilisation de la même valeur dans toutes les expressions lambda. Capturez la valeur de la variable dans une variable locale. Dans l'exemple précédent :

  • La variable de boucle i est affectée à buttonNumber.
  • buttonNumber est utilisé dans l’expression lambda.

Vous pouvez également utiliser une boucle foreach avec Enumerable.Range, qui ne souffre pas du problème précédent :

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

EventCallback

Un scénario courant avec les composants imbriqués exécute une méthode dans un composant parent lorsqu’un événement de composant enfant se produit. Un événement onclick se produisant dans le composant enfant est un cas d’usage courant. Pour exposer des événements entre les composants, utilisez un EventCallback. Un composant parent peut affecter une méthode de rappel au EventCallback d’un composant enfant.

Le composant Child suivant montre comment le gestionnaire de onclick d’un bouton est configuré pour recevoir un délégué EventCallback du ParentComponent de l’exemple. Le EventCallback est typé avec MouseEventArgs, qui convient à un événement onclick à partir d’un périphérique.

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

Le composant Parent définit le EventCallback<TValue> (OnClickCallback) de l’enfant sur sa méthode ShowMessage.

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

Lorsque le bouton est sélectionné dans le ChildComponent :

  • La méthode ShowMessage du composant Parent est appelée. message est mis à jour et affiché dans le composant Parent.
  • Un appel à StateHasChanged n’est pas requis dans la méthode du rappel (ShowMessage). StateHasChanged est appelé automatiquement pour renvoyer le composant Parent, tout comme les événements enfants déclenchent une nouvelle génération de composant dans les gestionnaires d’événements qui s’exécutent dans l’enfant. Pour plus d’informations, consultez le rendu de composants Razor ASP.NET Core.

Utilisez EventCallback et EventCallback<TValue> pour la gestion des événements et les paramètres de composant de liaison.

Préférez le EventCallback<TValue> fortement typé à EventCallback. EventCallback<TValue> fournit des commentaires améliorés sur l’erreur lorsqu’un type inapproprié est utilisé, guidant les utilisateurs du composant vers une implémentation appropriée. Comme pour d’autres gestionnaires d’événements d’interface utilisateur, la spécification du paramètre d’événement est facultative. Utilisez EventCallback lorsqu’aucune valeur n’est passée au rappel.

EventCallback et EventCallback<TValue> autorisent les délégués asynchrones. EventCallback est faiblement typé et permet de passer n’importe quel type d’argument dans InvokeAsync(Object). EventCallback<TValue> est fortement typé et nécessite de passer un argument T dans InvokeAsync(T) qui est assignable à TValue.

Appelez un EventCallback ou EventCallback<TValue> avec InvokeAsync et attendez Task :

await OnClickCallback.InvokeAsync({ARGUMENT});

Dans l’exemple précédent, l’espace réservé {ARGUMENT} est un argument facultatif.

L’exemple parent-enfant suivant montre la technique.

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

La deuxième occurrence du composant Child2 illustre un appel asynchrone, mais également la nouvelle valeur message2 est affectée et rendue avec un délai de deux secondes.

Empêcher les actions par défaut

Utilisez l’attribut de directive @on{DOM EVENT}:preventDefault pour empêcher l’action par défaut d’un événement, où l’espace réservé {DOM EVENT} est un événement DOM (Document Object Model).

Lorsqu’une touche est sélectionnée sur un périphérique d’entrée et que le focus d’élément se trouve sur une zone de texte, un navigateur affiche normalement le caractère de la touche dans la zone de texte. Dans l’exemple suivant, le comportement par défaut est empêché en spécifiant l’attribut de directive @onkeydown:preventDefault. Lorsque le focus se trouve sur l’élément <input>, le compteur s’incrémente avec la séquence de touches Maj++. Le caractère + n’est pas affecté à la valeur de l’élément <input>. Pour plus d’informations sur keydown, consultez l’événement MDN Web Docs: Document: keydown.

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

La spécification de l’attribut @on{DOM EVENT}:preventDefault sans valeur équivaut à @on{DOM EVENT}:preventDefault="true".

Une expression est également une valeur autorisée de l’attribut. Dans l’exemple suivant, shouldPreventDefault est un champ bool défini sur true ou false :

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

...

@code {
    private bool shouldPreventDefault = true;
}

Arrêter la propagation d’événements

Utilisez l’attribut de directive @on{DOM EVENT}:stopPropagation pour arrêter la propagation d’événements dans l’étendue Blazor. {DOM EVENT} est un espace réservé pour un événement DOM.

L’effet de l’attribut de directive stopPropagation est limité à l’étendue Blazor et ne s’étend pas au DOM HTML. Les événements doivent se propager à la racine DOM HTML avant que Blazor puisse agir dessus. Pour qu’un mécanisme empêche la propagation d’événements DOM HTML, envisagez l’approche suivante :

Dans l’exemple suivant, la case à cocher empêche les événements de clic du deuxième <div> enfant de se propager au <div> parent. Étant donné que les événements de clic propagés déclenchent normalement la méthode OnSelectParentDiv, la sélection du deuxième <div> enfant entraîne l’affichage du message parent <div>, sauf si la case est cochée.

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

Focus sur un élément

Appelez FocusAsync sur une référence d’élément pour placer le focus sur un élément dans le code. Dans l’exemple suivant, sélectionnez le bouton pour placer le focus sur l’élément <input>.

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