如何在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
相关产品推荐
相关产品推荐

