You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MudBlazor:如何为绑定模型动态添加的元素设置焦点?

解决MudTreeView新增节点后MudTextField自动聚焦的优雅方案

一、MudBlazor原生方案(推荐)

核心思路是通过标记需要聚焦的节点,在组件渲染完成后触发聚焦操作,替代定时器轮询。

  1. 定义变量跟踪需要聚焦的节点唯一标识:
private Guid? _pendingFocusNodeId;
  1. 添加节点时记录该节点的ID:
private void AddNode()
{
    var newNode = new TreeViewItem { Id = Guid.NewGuid(), Text = "新节点", IsEditing = true };
    // 将新节点添加到绑定模型的逻辑...
    _pendingFocusNodeId = newNode.Id; // 标记需要聚焦的节点
}
  1. 在TreeView节点模板中绑定MudTextField的引用,结合OnAfterRenderAsync触发聚焦:
<MudTreeView Items="@TreeItems">
    <ItemTemplate>
        <MudTreeViewItem @bind-Expanded="@context.Expanded">
            @if (context.IsEditing)
            {
                <MudTextField @ref="@GetTextFieldRef(context.Id)" 
                              @bind-Value="@context.Text" 
                              Immediate="true" />
            }
            else
            {
                <MudText>@context.Text</MudText>
            }
        </MudTreeViewItem>
    </ItemTemplate>
</MudTreeView>

@code {
    private Dictionary<Guid, MudTextField> _textFieldRefs = new();

    private MudTextField GetTextFieldRef(Guid nodeId)
    {
        if (!_textFieldRefs.ContainsKey(nodeId))
            _textFieldRefs[nodeId] = new MudTextField();
        return _textFieldRefs[nodeId];
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (_pendingFocusNodeId.HasValue && _textFieldRefs.TryGetValue(_pendingFocusNodeId.Value, out var textField))
        {
            // 等待DOM元素就绪,替代轮询逻辑
            await textField.InputReference.WaitForElementAsync();
            // 触发聚焦并滚动到视图
            await textField.FocusAsync();
            await textField.InputReference.Current.ScrollIntoViewAsync(new ScrollIntoViewOptions { Behavior = ScrollBehavior.Smooth });
            // 清除标记避免重复触发
            _pendingFocusNodeId = null;
        }
        await base.OnAfterRenderAsync(firstRender);
    }
}

这里利用MudBlazor原生的InputReference.WaitForElementAsync()方法,等待DOM元素就绪后执行操作,比定时器更可靠高效。

二、JavaScript方案(备选)

如果原生方案适配特殊场景有困难,可通过JS监听DOM元素新增来触发聚焦:

  1. 注入IJSRuntime:
[Inject] private IJSRuntime JSRuntime { get; set; }
  1. 添加节点后调用JS方法:
private async Task AddNode()
{
    var newNode = new TreeViewItem { Id = Guid.NewGuid(), Text = "新节点", IsEditing = true };
    // 将新节点添加到绑定模型的逻辑...
    await JSRuntime.InvokeVoidAsync("focusNewNodeInput", $"node-input-{newNode.Id}");
}
  1. 在wwwroot/js目录下创建tree-focus.js文件:
window.focusNewNodeInput = function(inputId) {
    const observer = new MutationObserver((mutations) => {
        mutations.forEach(mutation => {
            if (mutation.addedNodes.length) {
                const input = document.getElementById(inputId);
                if (input) {
                    input.focus();
                    input.scrollIntoView({ behavior: 'smooth' });
                    observer.disconnect(); // 找到元素后停止监听
                }
            }
        });
    });
    observer.observe(document.body, { childList: true, subtree: true });
}
  1. 在_Host.cshtml(或index.html)中引入该文件:
<script src="~/js/tree-focus.js"></script>
  1. 给MudTextField设置唯一ID:
<MudTextField Id="@($"node-input-{context.Id}")" ... />

三、关键注意事项

  • 确保新增节点的IsEditing状态为true,否则MudTextField不会渲染;
  • 原生方案中InputReference.WaitForElementAsync()无需额外延迟,内部已处理DOM就绪逻辑;
  • JS方案需保证节点输入框的ID唯一,避免定位错误。

内容的提问来源于stack exchange,提问作者lesscode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 23:12:30