存储对运行时创建的组件的引用

Storing references to components created at runtime

给定以下 Blazor 组件:

@foreach (var col in columns)
{
    @foreach (row in rows)
    {
        <MyInput @onkeydown="KeyDown" @ref="NewInput"></MyInput>
    }
}

@code {
    private List<MyInput> inputs = new List<MyInput>();

    private MyInput NewInput
    {
        get { return _NewInput; }
        set
        {
            _NewInput = value;
            inputs.Add(_NewInput);
        }
    }
    MyInput _NewInput;

    private async Task KeyDown(KeyboardEventArgs args)
    {
        if (args.Code == "ArrowDown")
        {
            //TODO: Find out which dynamic MyInput-instance
            //      within the inputs collection triggered the event
        }
    }
}

我正在尝试使用箭头键在 MyInputs 之间添加光标导航。为此,我显然需要知道哪个 MyInput 组件触发了按键事件。

我通过滥用@ref 属性 设法将所有 MyInput 实例存储到一个列表中,但我无法弄清楚我的列表中的哪个实例触发了该事件。

Blazor 是否提供任何方法来找出哪个动态创建的 MyInput 实例触发了事件?

假设您定义了一个名为“

的组件

ChildComponent.razor

<div>@ID.ToString()</div>

@code {

    [Parameter]
    public int ID { get; set; }

}

其中有一个参数属性 ID,由父组件提供,像这样:

ParentComponent.razor

@for (int i = 0; i < 10; i++)
{
    <ChildComponent @ref="component" ID="i" />
}

@code
{
    private ChildComponent component { set => components.Add(value); }

    List<ChildComponent> components = new List<ChildComponent>();

    protected override void OnInitialized()
    {
        foreach (var component in components)
        {
           Console.WriteLine(component.ID);
        }
    }
}

现在,您可以通过 ID 识别组件。一种简单有效的方法,尽管您可以通过其他方式做到这一点。

注意:这是错误的:

<MyInput @onkeydown="KeyDown" @ref="NewInput"></MyInput>

因为您将方法名称“KeyDown”分配给了@onkeydown 编译器指令,它仅适用于Html 标记,不适用于组件。

你可以这样做:

<MyInput ID="id" @ref="NewInput"></MyInput>
请注意,

ID 应该是在 MyInput 组件中定义的参数 属性,它是一个子组件。您还必须定义一个 EventCallback,它应该从 keydown 事件的事件处理程序中触发。在当前情况下,EventCallback 应该 return 到父组件,其 html 标记中的子组件的 ID,比如输入 html 元素, keydown 事件发生.我希望你能成功地理解我所说的...如果没有,请不要犹豫提问。

更新:

注意:我在之前的代码示例中添加了一些代码,以演示如何在您点击每个 ChildComponent 中嵌入的输入 Html 元素的 KeyDown 按钮时 return 每个 ChildComponent 的 ID子组件。此外,我的代码还演示了如何在 KeyDown 事件发生时 return 对每个组件的引用:

ChildComponent.razor

<input type="text" @onkeydown="@KeyDown" />

       
@code {

    [Parameter]
    public int ID { get; set; }

   // [Parameter]
   // public EventCallback<int> CallBack { get; set; }

  
    [Parameter]
    public EventCallback<ChildComponent> CallBack { get; set; }

     private void KeyDown(KeyboardEventArgs args)
    {
      //  if (args.Code == "ArrowDown")
      //  {
      //      InvokeAsync(() => { CallBack.InvokeAsync(ID); });
      //  }

        if (args.Code == "ArrowDown")
        {
            InvokeAsync(() => { CallBack.InvokeAsync(this); });
        }
    }

}

ParentComponent.razor

<div>@output</div>

@for (int i = 0; i < 10; i++)
{
    <ChildComponent CallBack="ShowID" @ref="component" ID="i" />
}


@code
{
    private ChildComponent component { set => components.Add(value); }

    List<ChildComponent> components = new List<ChildComponent>();

    protected override void OnInitialized()
    {
        foreach (var component in components)
        {
           Console.WriteLine(component.ID);
        }
    }

    private string output = "";

    // private void ShowID(int id)
    // {
    //     output = id.ToString();
    // }


    private void ShowID(ChildComponent child)
    {
        output = child.ID.ToString(); 
    }
}