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

如何在Blazor中实现按钮触发的待办事项按日期排序?

Blazor待办事项按日期排序功能修复方案

问题描述

我是一名.NET新手,需要为我的待办事项列表实现按日期排序的功能。我编写了如下代码,但排序功能无法生效,希望通过按钮触发排序。我认为@foreach是问题所在,已经尝试过多种改写方式,但都没有效果。我在谷歌上搜索了各类资料,但都无法适配我的现有代码。

原始代码:

@page "/todo"
@using System.Linq

<PageTitle>Todo</PageTitle>

<h2>Progress bar</h2>
<label for="file">Progress:</label>
<progress id="file" value=@PocetSplnenych max=@CelkovyPocet></progress>

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>
            <input type="checkbox" @bind="todo.IsDone" />
            <input @bind="todo.Title" />
            <input @bind="todo.date" />
            <input @bind="todo.Priority" />
        </li>
    }
</ul>

<h3>Hotové (@todos2.Count(todo => !todo.IsDone))</h3>

<ul>
    @foreach (var todo in todos2)
    {
        <li>
            <input type="checkbox" @bind="todo.IsDone" />
            <input @bind="todo.Title" />
            <input @bind="todo.date" />
            <input @bind="todo.Priority" />
        </li>
    }
</ul>

<input placeholder="Úkol" @bind="newTodo" />
<input type="date" placeholder="Select a date" @bind="date" />
<input placeholder="Jaká je priorita?" @bind="newPriority" />
<button @onclick="AddTodo">přidat</button>
<button @onclick="Delete">smazat</button>
<button @onclick="Move">přesunout</button>
<button @onclick="Sort">Seřadit</button>

@code {
    private List<TodoItem> todos = new();
    private string? newTodo;
    private DateOnly date;
    private string? newPriority;

    private void Sort()
    {
        foreach (var received in todos.OrderBy(a => a.date)) 
        {
            @received.date
        }
    }
}    

问题分析

你的Sort方法没有实际修改绑定的数据源:

  1. 仅遍历排序后的结果,未更新todos集合的实际顺序
  2. 代码块中使用@received.date是无效的Razor语法,无法触发界面更新
  3. Blazor的UI渲染依赖组件状态变化,未修改数据源的情况下,界面不会自动刷新

修复方案

1. 修正Sort方法,更新数据源

将排序后的结果重新赋值给todos集合,Blazor会自动检测到集合变化并重新渲染界面:

private void Sort()
{
    // 用OrderBy排序后转成List,重新赋值给todos
    todos = todos.OrderBy(a => a.date).ToList();
}

2. 可选:手动触发状态更新(按需)

如果遇到界面未自动刷新的情况,可以在排序后手动通知组件状态变化:

private void Sort()
{
    todos = todos.OrderBy(a => a.date).ToList();
    StateHasChanged(); // 手动触发UI渲染,多数场景下可省略
}

3. 补充缺失的代码(确保完整运行)

原代码缺少todos2定义、TodoItem类及部分方法实现,补充后完整代码如下:

@page "/todo"
@using System.Linq

<PageTitle>Todo</PageTitle>

<h2>Progress bar</h2>
<label for="file">Progress:</label>
<progress id="file" value=@PocetSplnenych max=@CelkovyPocet></progress>

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>
            <input type="checkbox" @bind="todo.IsDone" />
            <input @bind="todo.Title" />
            <input @bind="todo.date" />
            <input @bind="todo.Priority" />
        </li>
    }
</ul>

<h3>Hotové (@todos2.Count(todo => !todo.IsDone))</h3>

<ul>
    @foreach (var todo in todos2)
    {
        <li>
            <input type="checkbox" @bind="todo.IsDone" />
            <input @bind="todo.Title" />
            <input @bind="todo.date" />
            <input @bind="todo.Priority" />
        </li>
    }
</ul>

<input placeholder="Úkol" @bind="newTodo" />
<input type="date" placeholder="Select a date" @bind="date" />
<input placeholder="Jaká je priorita?" @bind="newPriority" />
<button @onclick="AddTodo">přidat</button>
<button @onclick="Delete">smazat</button>
<button @onclick="Move">přesunout</button>
<button @onclick="Sort">Seřadit</button>

@code {
    private List<TodoItem> todos = new();
    private List<TodoItem> todos2 = new();
    private string? newTodo;
    private DateOnly date;
    private string? newPriority;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo, date = date, Priority = newPriority });
            newTodo = null;
            newPriority = null;
        }
    }

    private void Delete()
    {
        todos.RemoveAll(t => t.IsDone);
        todos2.RemoveAll(t => t.IsDone);
    }

    private void Move()
    {
        var doneItems = todos.Where(t => t.IsDone).ToList();
        todos.RemoveAll(t => t.IsDone);
        todos2.AddRange(doneItems);
    }

    private void Sort()
    {
        todos = todos.OrderBy(a => a.date).ToList();
    }

    public class TodoItem
    {
        public bool IsDone { get; set; }
        public string? Title { get; set; }
        public DateOnly date { get; set; }
        public string? Priority { get; set; }
    }

    private int PocetSplnenych => todos.Count(t => t.IsDone) + todos2.Count(t => t.IsDone);
    private int CelkovyPocet => todos.Count + todos2.Count;
}

关键说明

  • OrderBy返回的是IEnumerable<T>,必须通过ToList()转换为List<TodoItem>才能重新赋值给todos
  • @foreach本身没有问题,只要数据源顺序改变,Blazor会自动重新渲染列表
  • 补充的代码确保了组件的完整性,可直接运行测试排序功能

内容的提问来源于stack exchange,提问作者Pavel Chřibek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 04:15:18