如何在Blazor中不使用输入标记检测按键按下

19
我希望能在Blazor中捕获键盘输入,而不使用HTML INPUT标签。一旦按下键,我将显示一个图形来表示所按下的字母。

类似于这样的东西

@page "/counter"
@using Microsoft.AspNetCore.Components.Web

<div @onkeypress="e => KeyPress(e)">
    Press any letter key
</div>

@code {

    private void KeyPress(KeyboardEventArgs e)
    {
        var letter = e.Key;
    }
}

当我在KeyPress方法上设置断点时,似乎该方法没有被调用。非常感谢任何帮助。


1
div元素需要包含焦点以拦截按键。 - Mister Magoo
3个回答

24

如果仍有人需要解决方案,我认为现在在 .NET 5 中使用 Blazor 可以实现此功能而无需 js。设置焦点和 tabindex 很重要,当您失去焦点或将焦点设置到另一个元素时,这将不起作用。这对我很有效:

    <table @ref="testRef" tabindex="0" @onkeydown="HandleKeyDown">
    <thead>
        <tr>
            <th>
                Pressed Key
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                @pressedKey
            </td>
        </tr>
    </tbody>
    </table>

    private ElementReference testRef;
    private string pressedKey;
    
    private void HandleKeyDown(KeyboardEventArgs e)
    {
        pressedKey = e.Key;
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await testRef.FocusAsync();
        }
    }

18

您已经接近成功了,但是您忘记让 div 具有焦点。以下是步骤:

0.- 添加 tabindex 标签,使您的 div 可以获得焦点:

<div 
    class="jumbotron"
    @onkeydown="@KeyDown"
    tabindex="0"
    @ref="myDiv" >
   <h1 class="display-4">
       @letter
   </h1>   
</div>

1.- 创建一个JS代码,以设置焦点到你的div,在例如_Host.cshtml这个文件中:


    <script>
        window.SetFocusToElement = (element) => {
            element.focus();
        };
    </script>

这个函数以元素引用作为参数。

2. 在组件渲染后调用此函数。


protected ElementReference myDiv;  // set by the @ref attribute

protected async override Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender) 
    {
        await JSRuntime.InvokeVoidAsync("SetFocusToElement", myDiv);
    }            
}  

3. - 实现自己的 KeyDown

protected void KeyDown(KeyboardEventArgs e)
{
    letter = $"Pressed: [{e.Key}]";
}

请注意,这不是Blazor的问题,只是默认的html和js行为。我在编写游戏时学会了这一点,可以在Blagario实验室中查看。

运行:

Flappy Blazor Bird

演示见Flappy Blazor Bird

编辑于2019年11月:

代码改进由@Quango完成(非常感谢)


建议:更改js代码,使其通用: - Quango
1
实际上,@dani更好的方法是使用Blazor的@ref功能并传递元素,然后代码只需[element].focus() - 这避免了分配ID的需要。 - Quango
@daniherrera 没问题。我还修改了调用为 InvokeVoidAsync,因为它没有返回值。使用 ElementReference 方法是推荐的,因为它避免了使用 id 的需要 - 例如,如果多次使用组件。 - Quango

0

这里有一种更容易的方法来实现它(无需使用JS)。 首先创建一个像这样的div:

<div @ref="keyDownDiv" @onkeydown="KeyPress"></div>

在你的代码中添加一个变量作为参考:

private ElementReference keyDownDiv;

现在您可以使用这行代码:

await keyDownDiv.FocusAsync();

浏览器的焦点将设置在您的div上,并触发OnKeyDown事件。 提示:如果用户按下其他按钮,焦点将改变,它将不再起作用!在这种情况下,只需再次使用FocusAsync。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接