ASP.NET Core Blazor のイベント処理

次の @on{DOM EVENT}="{DELEGATE}" Razor 構文を使用して、Razor コンポーネント マークアップでデリゲート イベント ハンドラーを指定します。

イベント処理の場合:

  • Task を返す非同期デリゲート イベント ハンドラーがサポートされています。
  • デリゲート イベント ハンドラーによって UI レンダリングが自動的にトリガーされるため、StateHasChanged を手動で呼び出す必要はありません。
  • 例外がログされます。

コード例を次に示します。

  • UI 内でボタンが選択されたときに UpdateHeading メソッドを呼び出します。
  • UI 内でチェックボックスが変更されたときに CheckChanged メソッドを呼び出します。

Pages/EventHandlerExample1.razor:

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

<h1>@currentHeading</h1>

<p>
    <label>
        New title
        <input @bind="newHeading" />
    </label>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

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

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

    private void UpdateHeading()
    {
        currentHeading = $"{newHeading}!!!";
    }

    private void CheckChanged()
    {
        checkedMessage = $"Last changed at {DateTime.Now}";
    }
}
@page "/event-handler-example-1"

<h1>@currentHeading</h1>

<p>
    <label>
        New title
        <input @bind="newHeading" />
    </label>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

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

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

    private void UpdateHeading()
    {
        currentHeading = $"{newHeading}!!!";
    }

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

UpdateHeading は、以下の例では次のようになります。

  • ボタンが選択されると、非同期に呼び出されます。
  • 2 秒間待機してから、見出しを更新します。

Pages/EventHandlerExample2.razor:

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

<h1>@currentHeading</h1>

<p>
    <label>
        New title
        <input @bind="newHeading" />
    </label>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

@code {
    private string currentHeading = "Initial heading";
    private string newHeading;

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

        currentHeading = $"{newHeading}!!!";
    }
}
@page "/event-handler-example-2"

<h1>@currentHeading</h1>

<p>
    <label>
        New title
        <input @bind="newHeading" />
    </label>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

@code {
    private string currentHeading = "Initial heading";
    private string newHeading;

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

        currentHeading = $"{newHeading}!!!";
    }
}

イベント引数

組み込みのイベント引数

イベント引数の型をサポートするイベントの場合、イベント メソッド定義でイベント パラメーターを指定する必要があるのは、イベントの型がメソッドで使用されている場合のみです。 次の例では、ReportPointerLocation メソッドで MouseEventArgs が使用されています。これにより、ユーザーが UI 内でボタンを選択すると、マウスの座標を報告するメッセージ テキストが設定されます。

Pages/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}";
    }
}
@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}";
    }
}

サポートされている EventArgs を次の表に示します。

event クラス ドキュメント オブジェクト モデル (DOM) イベントと注記
クリップボードのトピック ClipboardEventArgs oncut, oncopy, onpaste
ドラッグ DragEventArgs ondrag, ondragstart, ondragenter, ondragleave, ondragover, ondrop, ondragend

DataTransfer および DataTransferItem では、ドラッグされた項目データを保持します。

HTML ドラッグ アンド ドロップ API と共に JS 相互運用を使用し、Blazor アプリにドラッグ アンド ドロップを実装します。
Error ErrorEventArgs onerror
event EventArgs 全般
onactivate, onbeforeactivate, onbeforedeactivate, ondeactivate, onfullscreenchange, onfullscreenerror, onloadeddata, onloadedmetadata, onpointerlockchange, onpointerlockerror, onreadystatechange, onscroll

クリップボード
onbeforecut, onbeforecopy, onbeforepaste

入力
oninvalid, onreset, onselect, onselectionchange, onselectstart, onsubmit

メディア
oncanplay, oncanplaythrough, oncuechange, ondurationchange, onemptied, onended, onpause, onplay, onplaying, onratechange, onseeked, onseeking, onstalled, onstop, onsuspend, ontimeupdate, ontoggle, onvolumechange, onwaiting

EventHandlers は、イベント名とイベント引数の型の間のマッピングを構成する属性を保持します。
フォーカス FocusEventArgs onfocus, onblur, onfocusin, onfocusout

relatedTarget のサポートは含まれません。
入力 ChangeEventArgs onchange, oninput
キーボード KeyboardEventArgs onkeydown, onkeypress, onkeyup
マウス MouseEventArgs onclick, oncontextmenu, ondblclick, onmousedown, onmouseup, onmouseover, onmousemove, onmouseout
マウス ポインター PointerEventArgs onpointerdown, onpointerup, onpointercancel, onpointermove, onpointerover, onpointerout, onpointerenter, onpointerleave, ongotpointercapture, onlostpointercapture
マウス ホイール WheelEventArgs onwheel, onmousewheel
進行状況 ProgressEventArgs onabort, onload, onloadend, onloadstart, onprogress, ontimeout
タッチ TouchEventArgs ontouchstart, ontouchend, ontouchmove, ontouchenter, ontouchleave, ontouchcancel

TouchPoint は、タッチを検知するデバイス上の単一接触点を表します。
event クラス ドキュメント オブジェクト モデル (DOM) イベントと注記
クリップボードのトピック ClipboardEventArgs oncut, oncopy, onpaste
ドラッグ DragEventArgs ondrag, ondragstart, ondragenter, ondragleave, ondragover, ondrop, ondragend

DataTransfer および DataTransferItem では、ドラッグされた項目データを保持します。

HTML ドラッグ アンド ドロップ API と共に JS 相互運用を使用し、Blazor アプリにドラッグ アンド ドロップを実装します。
Error ErrorEventArgs onerror
event EventArgs 全般
onactivate, onbeforeactivate, onbeforedeactivate, ondeactivate, onfullscreenchange, onfullscreenerror, onloadeddata, onloadedmetadata, onpointerlockchange, onpointerlockerror, onreadystatechange, onscroll

クリップボード
onbeforecut, onbeforecopy, onbeforepaste

入力
oninvalid, onreset, onselect, onselectionchange, onselectstart, onsubmit

メディア
oncanplay, oncanplaythrough, oncuechange, ondurationchange, onemptied, onended, onpause, onplay, onplaying, onratechange, onseeked, onseeking, onstalled, onstop, onsuspend, ontimeupdate, onvolumechange, onwaiting

EventHandlers は、イベント名とイベント引数の型の間のマッピングを構成する属性を保持します。
フォーカス FocusEventArgs onfocus, onblur, onfocusin, onfocusout

relatedTarget のサポートは含まれません。
入力 ChangeEventArgs onchange, oninput
キーボード KeyboardEventArgs onkeydown, onkeypress, onkeyup
マウス MouseEventArgs onclick, oncontextmenu, ondblclick, onmousedown, onmouseup, onmouseover, onmousemove, onmouseout
マウス ポインター PointerEventArgs onpointerdown, onpointerup, onpointercancel, onpointermove, onpointerover, onpointerout, onpointerenter, onpointerleave, ongotpointercapture, onlostpointercapture
マウス ホイール WheelEventArgs onwheel, onmousewheel
進行状況 ProgressEventArgs onabort, onload, onloadend, onloadstart, onprogress, ontimeout
タッチ TouchEventArgs ontouchstart, ontouchend, ontouchmove, ontouchenter, ontouchleave, ontouchcancel

TouchPoint は、タッチを検知するデバイス上の単一接触点を表します。

詳細については、次のリソースを参照してください。

  • ASP.NET Core 参照ソース内の EventArgs クラス (dotnet/aspnetcore main ブランチ)

    注意

    ASP.NET Core 参照ソースへのドキュメント リンクを使用すると、リポジトリの main ブランチが読み込まれます。このブランチは、ASP.NET Core の次回リリースに向けて行われている製品単位の現在の開発を表します。 別のリリースのブランチを選択するには、 [Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使用して、そのブランチを選択します。 たとえば、ASP.NET Core 5.0 リリースの場合は、release/5.0 ブランチを選択します。

  • MDN Web ドキュメント:GlobalEventHandlers:各 DOM イベントをサポートする HTML 要素に関する情報が含まれています。

カスタム イベント引数

Blazor ではカスタム イベント引数がサポートされています。このため、カスタム イベントを使用して任意のデータを .NET イベント ハンドラーに渡すことができます。

全般構成

カスタム イベント引数を使用したカスタム イベントは、一般に次の手順によって有効にされます。

  1. JavaScript では、ソース イベントからカスタム イベント引数オブジェクトをビルドするための関数を定義します。

    function eventArgsCreator(event) { 
      return {
        customProperty1: 'any value for property 1',
        customProperty2: event.srcElement.value
      };
    }
    
  2. Blazor <script> の直後にある wwwroot/index.html (Blazor WebAssembly) または Pages/_Host.cshtml (Blazor Server) で前のハンドラーにカスタム イベントを登録します。

    <script>
        Blazor.registerCustomEventType('customevent', {
            createEventArgs: eventArgsCreator;
        });
    </script>
    

    注意

    registerCustomEventType の呼び出しは、1 つのイベントにつき 1 回だけスクリプト内で実行されます。

  3. イベント引数のクラスは次のように定義します。

    public class CustomEventArgs : EventArgs
    {
        public string CustomProperty1 {get; set;}
        public string CustomProperty2 {get; set;}
    }
    
  4. カスタム イベントに関する EventHandlerAttribute 属性注釈を追加することによって、イベント引数を使用したカスタム イベントを接続します。 このクラスにメンバーは必要ありません。

    [EventHandler("oncustomevent", typeof(CustomEventArgs), enableStopPropagation: true, enablePreventDefault: true)]
    static class EventHandlers
    {
    }
    
  5. 1 つまたは複数の HTML 要素に対してイベント ハンドラーを登録します。 Javascript の形式でデリゲート ハンドラー メソッドに渡されたデータにアクセスします。

    <button @oncustomevent="HandleCustomEvent">Handle</button>
    
    @code
    {
        void HandleCustomEvent(CustomEventArgs eventArgs)
        {
            // eventArgs.CustomProperty1
            // eventArgs.CustomProperty2
        }
    }
    

DOM 上でカスタム イベントが発生するたびに、Javascript から渡されたデータを使用してイベント ハンドラーが呼び出されます。

カスタム イベントを発生させようとしている場合は、bubbles を有効にするために、その値を true に設定する必要があります。 それを行わない場合は、イベントが発生しても、処理用の Blazor ハンドラーが C# カスタム EventHandlerAttribute メソッドに到達することはありません。 詳細については、「MDN Web Docs: イベントのバブリング」を参照してください。

カスタム クリップボードの貼り付けイベントの例

次の例では、貼り付けの時刻とユーザーが貼り付けたテキストを含む、カスタム クリップボードの貼り付けイベントを受け取ります。

イベントのカスタム名 (oncustompaste) と、このイベントのイベント引数を保持する .NET クラス (CustomPasteEventArgs) を宣言します。

CustomEvents.cs:

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

EventArgs サブクラスにデータを提供する JavaScript コードを追加します。 wwwroot/index.html または Pages/_Host.cshtml ファイル内で、Blazor スクリプトの直後に次の <script> タグとコンテンツを追加します。 次の例では、テキストの貼り付けのみを処理しますが、任意の JavaScript API を使用して、ユーザーによる他の種類のデータ (画像など) の貼り付けを処理することもできます。

Blazor スクリプトの直後の wwwroot/index.html (Blazor WebAssembly) または Pages/_Host.cshtml (Blazor Server)

<script>
    Blazor.registerCustomEventType('custompaste', {
        browserEventName: 'paste',
        createEventArgs: event => {
            return {
                eventTimestamp: new Date(),
                pastedData: event.clipboardData.getData('text')
            };
        }
    });
</script>

上記のコードでは、ネイティブの paste イベントが発生したときに、次のことをブラウザーに指示します。

  • custompaste イベントを発生させる。
  • 次に示したカスタムロジックを使用して、イベント引数データを指定する。
    • eventTimestamp の場合は、新しい日付を作成します。
    • pastedData の場合は、クリップボード データをテキストとして取得します。 詳細については、「MDN Web Docs: ClipboardEvent.clipboardData」を参照してください。

イベント名の規則は、.NET と JavaScript で異なります。

  • .NET では、イベント名の先頭に "on" が付きます。
  • JavaScript では、イベント名にプレフィックスは付きません。

Razor コンポーネントでは、カスタム ハンドラーを要素にアタッチします。

Pages/CustomPasteArguments.razor:

@page "/custom-paste-arguments"

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

ラムダ式

ラムダ式 は、デリゲート イベント ハンドラーとしてサポートされています。

Pages/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";
}
@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";
}

要素のセットを反復処理するときなど、C# メソッド パラメーターを使用して追加の値に集中すると便利な場合がよくあります。 次の例では、3 つのボタンを作成します。それぞれを押すと、UpdateHeading が呼び出され、次のデータが渡されます。

  • e に対してイベント引数 (MouseEventArgs)。
  • buttonNumber に対してボタン番号。

Pages/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}";
    }
}
@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}";
    }
}

注意

前の for ループの例の i などのラムダ式内で、ループ変数を直接使用し ない でください。 そうしないと、すべてのラムダ式で同じ変数が使用され、すべてのラムダで同じ値が使用されることになります。 常にローカル変数の変数値をキャプチャしてから使用してください。 前の例の場合:

  • ループ変数 ibuttonNumber に割り当てられます。
  • buttonNumber はラムダ式で使用されます。

EventCallback

入れ子になったコンポーネントがある一般的なシナリオでは、子コンポーネントのイベントが発生したときに親コンポーネントのメソッドを実行します。 子コンポーネントで発生する onclick イベントが、一般的なユース ケースです。 コンポーネント間にわたってイベントを公開するには、EventCallback を使用します。 親コンポーネントでは、コールバック メソッドを子コンポーネントの EventCallback に割り当てることができます。

次の Child は、ボタンの onclick ハンドラーがどのように、サンプルの ParentComponent から EventCallback デリゲートを受け取るように設定されているかを示しています。 EventCallbackMouseEventArgs によって型指定されます。これは、周辺機器の onclick イベントに適しています。

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

Parent コンポーネントでは、子の EventCallback<TValue> (OnClickCallback) を ShowMessage メソッドに設定しています。

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

ChildComponent でボタンが選択されると:

  • Parent コンポーネントの ShowMessage メソッドが呼び出されます。 message が更新されて、Parent コンポーネントに表示されます。
  • コールバックのメソッド (ShowMessage) 内に、StateHasChanged の呼び出しは必要ありません。 StateHasChanged は、子イベントが子の中で実行されるイベント ハンドラーでコンポーネントのレンダリングをトリガーするのと同様に、Parent コンポーネントを再レンダリングするために自動的に呼び出されます。 詳細については、「ASP.NET Core Blazor コンポーネントのレンダリング」を参照してください。

EventCallbackEventCallback<TValue> では非同期デリゲートを使用できます。 EventCallback は弱く型指定されており、InvokeAsync(Object) では任意の型の引数を渡すことができます。 EventCallback<TValue> は厳密に型指定されており、InvokeAsync(T) では TValue に代入可能な T 引数を渡す必要があります。

<ChildComponent 
    OnClickCallback="@(async () => { await Task.Yield(); messageText = "Blaze It!"; })" />

InvokeAsync を使用して EventCallback または EventCallback<TValue> を呼び出して、Task を待機します。

await OnClickCallback.InvokeAsync(arg);

イベント処理とバインド コンポーネントのパラメーターには、EventCallbackEventCallback<TValue> を使用します。

厳密に型指定された EventCallback<TValue>EventCallback よりも優先します。 EventCallback<TValue> からは、強化されたエラー フィードバックがコンポーネントのユーザーに提供されます。 他の UI イベント ハンドラーと同様に、このイベント パラメーターの指定は省略可能です。 コールバックに渡される値がない場合は、EventCallback を使用します。

既定のアクションを止める

イベントの既定のアクションを防止するには、@on{DOM EVENT}:preventDefault を使用します。ここで、{DOM EVENT} プレースホルダーは、ドキュメント オブジェクト モデル (DOM) イベントです。

入力デバイスでキーが選択され、要素のフォーカスがテキスト ボックス上にあるときは、通常、ブラウザーによってテキスト ボックスにキーの文字が表示されます。 次の例では、@onkeydown:preventDefault ディレクティブ属性を指定することで、既定の動作が止められています。 <input> 要素にフォーカスがある場合、カウンターはキー シーケンス Shift++ が押されるとインクリメントします。 + 文字は、<input> 要素の値に割り当てられていません。 keydown の詳細については、「MDN Web Docs: Document: keydown イベント」を参照してください。

Pages/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++;
        }
    }
}
@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++;
        }
    }
}

値なしで @on{DOM EVENT}:preventDefault 属性を指定することは、@on{DOM EVENT}:preventDefault="true" と同じことになります。

式は、許可されている属性値でもあります。 次の例では、shouldPreventDefaulttrue または false のいずれかに設定される bool フィールドです。

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

...

@code {
    private bool shouldPreventDefault = true;
}

イベント伝達を停止する

イベントの伝達を停止するには、@on{DOM EVENT}:stopPropagation ディレクティブ属性を使用します。ここで、{DOM EVENT} プレースホルダーはドキュメント オブジェクト モデル (DOM) イベントです。

次の例では、チェックボックスをオンにすると、2 番目の子 <div> からのクリック イベントが親の <div> に伝達されなくなります。 クリック イベントが伝達されると、通常、OnSelectParentDiv メソッドが起動されるので、2 番目の子 <div> を選択すると、チェックボックスがオンになっていない限り、親の div メッセージが表示されます。

Pages/EventHandlerExample7.razor:

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

<label>
    <input @bind="stopPropagation" type="checkbox" />
    Stop Propagation
</label>

<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 doesn't stop propagation when selected.
    </div>

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

<p>
    @message
</p>

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

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

    private void OnSelectChildDiv() =>
        message = $"A child div was selected. {DateTime.Now}";
}
@page "/event-handler-example-7"

<label>
    <input @bind="stopPropagation" type="checkbox" />
    Stop Propagation
</label>

<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 doesn't stop propagation when selected.
    </div>

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

<p>
    @message
</p>

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

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

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

要素にフォーカスを合わせる

コード内の要素にフォーカスを合わせるには、要素参照FocusAsync を呼び出します。 次の例では、ボタンを選択して <input> 要素にフォーカスを移動します。

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