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

如何在Blazor中实现位置列表自动滚动到已选中的列表项

Blazor 列表自动滚动到选中项解决方案

实现思路:

  • 给每个列表项绑定DOM元素引用,捕获选中项的元素节点
  • 利用Blazor的OnAfterRenderAsync生命周期(此时DOM已完全渲染,元素引用生效),调用滚动方法将选中项滚动到可视区域

代码实现示例

1. Razor 页面部分

<!-- 固定头部区域 -->
<div class="fixed-header">页面头部内容</div>

<!-- 可滚动列表区域 -->
<div class="location-list" style="height: calc(100vh - 120px); overflow-y: auto;">
    @foreach (var location in LocationList)
    {
        <!-- 给选中的位置项绑定元素引用 -->
        <div class="location-item @(location.IsSelected ? "highlight" : "")" 
             @onclick="() => SelectLocation(location)"
             @ref="@(location.IsSelected ? SelectedLocationRef : default)">
            @location.Name
        </div>
    }
</div>

<!-- 固定底部按钮区域 -->
<div class="fixed-footer">
    <button @onclick="GoToNextPage">继续</button>
</div>

2. 后台逻辑(.NET 7+ 原生实现)

.NET 7及以上版本内置了元素滚动方法,无需额外写JS:

public partial class LocationSelectPage : ComponentBase
{
    [Parameter]
    public int? SelectedLocationId { get; set; }
    
    private List<LocationModel> LocationList { get; set; } = new();
    private ElementReference SelectedLocationRef { get; set; }
    private bool _hasScrolledToSelected;

    protected override async Task OnInitializedAsync()
    {
        // 加载位置列表数据
        LocationList = await LoadLocationListData();
        // 回显选中状态
        if (SelectedLocationId.HasValue)
        {
            var selected = LocationList.FirstOrDefault(l => l.Id == SelectedLocationId.Value);
            if (selected != null)
            {
                selected.IsSelected = true;
            }
        }
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        // 仅当存在选中项且未执行过滚动时触发
        if (SelectedLocationId.HasValue && !_hasScrolledToSelected && SelectedLocationRef.Id != null)
        {
            await SelectedLocationRef.ScrollIntoViewAsync(new ScrollIntoViewOptions
            {
                Block = ScrollLogicalPosition.Center, // 滚动到可视区域中间
                Behavior = ScrollBehavior.Smooth // 平滑滚动,不需要可设为Auto
            });
            _hasScrolledToSelected = true;
        }
    }

    // 其他业务方法
    private void SelectLocation(LocationModel location)
    {
        foreach (var item in LocationList)
        {
            item.IsSelected = item.Id == location.Id;
        }
        SelectedLocationRef = default;
        _hasScrolledToSelected = false;
    }

    private Task<List<LocationModel>> LoadLocationListData()
    {
        // 实现你的数据加载逻辑
        return Task.FromResult(new List<LocationModel>());
    }

    private void GoToNextPage()
    {
        // 实现跳转逻辑
    }
}

// 位置模型示例
public class LocationModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsSelected { get; set; }
}

3. .NET 6及更低版本兼容实现

如果使用.NET 6或更早版本,需要通过JS互操作实现滚动:
首先在前端入口文件(WebAssembly为wwwroot/index.html,Blazor Server为Pages/_Layout.cshtml)添加JS方法:

<script>
window.scrollToElement = (element) => {
    if (element) {
        element.scrollIntoView({
            block: 'center',
            behavior: 'smooth'
        });
    }
}
</script>

修改后台的OnAfterRenderAsync逻辑即可:

[Inject]
private IJSRuntime JSRuntime { get; set; }

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (SelectedLocationId.HasValue && !_hasScrolledToSelected && SelectedLocationRef.Id != null)
    {
        await JSRuntime.InvokeVoidAsync("scrollToElement", SelectedLocationRef);
        _hasScrolledToSelected = true;
    }
}

注意事项

  • 确保列表数据完全加载完成后再执行滚动逻辑,异步加载数据完成后需要调用StateHasChanged触发渲染
  • _hasScrolledToSelected标记用于避免每次页面重渲染都重复触发滚动,选中项变更时可重置该标记重新触发滚动
  • 滚动参数可根据需求调整,block设为start则滚动到可视区域顶部,设为end则滚动到可视区域底部

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 18:39:05