Blazor开发:如何逐个展示列表中的问题
Blazor分步展示单个问题的实现方案
我正在开发一款Blazor应用,需要向用户逐个提问,完成当前问题后再进入下一个。我有一个问题列表,希望分步展示每个问题,而非一次性展示所有。
现有可行的全量展示代码
如果要在单个页面展示所有问题,以下Index.razor代码可以正常运行:
@foreach (var item in items) { <h2>@item.Question</h2> } @code { List<Item> items = new(); protected override async Task OnInitializedAsync() { items = await HttpClient.GetFromJsonAsync<List<Item>>(NavigationManager.BaseUri + "items"); } }
其中Item类定义如下:
public class Item { public int Id { get; set; } public string Question { get; set; } }
当前遇到的问题
我需要一次只展示一个问题,尝试直接调用列表中指定问题的代码无法运行:
@* 此代码无法运行 *@ <h2>@items[3].Question</h2> @code { List<Item> items = new(); protected override async Task OnInitializedAsync() { items = await HttpClient.GetFromJsonAsync<List<Item>>(NavigationManager.BaseUri + "items"); } }
我猜测这和await异步操作有关,但不确定具体原因。解决这个问题后,我就能继续实现逐个调用列表项的功能。
补充代码说明
其余代码使用默认Blazor模板,DbContext定义如下:
public class QuestionsContext: DbContext { public DbSet<Item> Items { get; set; } public QuestionsContext(DbContextOptions options) : base(options) { } }
控制器代码如下:
[Route("items")] [ApiController] public class ItemController : Controller { private readonly QuestionsContext _db; public ItemController(QuestionsContext db) { _db = db; } [HttpGet] public async Task<ActionResult<List<Item>>> GetItems() { return await (_db.Items.ToListAsync()); } }
问题原因与解决方案
原因分析
直接访问items[3].Question会报错,核心原因是异步加载时机问题:
- Blazor组件会先执行初始渲染,此时
items还是空的List<Item>实例,没有任何元素,访问索引3会触发IndexOutOfRangeException。 - 异步方法
OnInitializedAsync在初始渲染之后才会完成数据加载,此时组件会重新渲染,但初始渲染时的索引访问已经抛出异常了。
解决方案
方案1:添加空值/长度判断
在渲染单个问题前,先检查items是否已经加载且包含足够元素:
@if (items != null && items.Count > 3) { <h2>@items[3].Question</h2> } else { <p>加载中...</p> } @code { List<Item> items = new(); protected override async Task OnInitializedAsync() { items = await HttpClient.GetFromJsonAsync<List<Item>>(NavigationManager.BaseUri + "items"); } }
方案2:使用当前问题索引变量,实现分步切换
为了实现逐个提问的完整功能,可以添加一个currentQuestionIndex变量来追踪当前展示的问题,配合按钮切换:
@if (items == null || items.Count == 0) { <p>加载中...</p> } else { <h2>@items[currentQuestionIndex].Question</h2> <button disabled="@(currentQuestionIndex == 0)" @onclick="PreviousQuestion">上一题</button> <button disabled="@(currentQuestionIndex == items.Count - 1)" @onclick="NextQuestion">下一题</button> } @code { List<Item> items = new(); private int currentQuestionIndex = 0; protected override async Task OnInitializedAsync() { items = await HttpClient.GetFromJsonAsync<List<Item>>(NavigationManager.BaseUri + "items"); } private void NextQuestion() { if (currentQuestionIndex < items.Count - 1) { currentQuestionIndex++; } } private void PreviousQuestion() { if (currentQuestionIndex > 0) { currentQuestionIndex--; } } }
额外优化建议
- 添加加载状态提示,提升用户体验;
- 若需要记录用户答题进度,可将
currentQuestionIndex存储到本地存储(localStorage)或后端数据库中。
内容的提问来源于stack exchange,提问作者moostang
相关产品推荐
相关产品推荐

