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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:31:08