【问题标题】:Sorting a filtered list对过滤后的列表进行排序
【发布时间】:2021-08-20 01:51:13
【问题描述】:

我有一个向用户显示的报告列表。我有允许以不同方式对列表进行排序的 a-tags(最后发布、最高赞成票等),并且我还有单独的 a-tags 可以根据特定报告变量过滤列表(报告状态为打开,关闭等)。

我正在想办法让过滤器在按下用于排序列表的 a-tag 时保持原位,反之亦然。

我尝试的是使用 statusId(设置为过滤列表的 ID)和 sortString(包含 “highest_award”的字符串设置模型em> 或 "last_update", 用于在 HomeController 中对列表进行排序),但我的想法完全错误。

有没有干净的方法来解决这个问题?

Index.cshtml

//List of sorting options -- *These are links that allow the user to sort the list as appropriate*
<ul class="nav nav-pills flex-column">
    <li><a asp-area="" asp-controller="Home" asp-action="Index" asp-route-sortString="@ViewData["AwardSort"]">Highest Awarded</a></li>
    <li><a asp-area="" asp-controller="Home" asp-action="Index" asp-route-sortString="@ViewData["UpdateSort"]">Last Updated</a></li>    
</ul>

...

//Filtering options set to status.Id -- *These are buttons that allow the user to filter the list as appropriate according to a set statusId for each article*
@foreach (ReportStatus status in Model.Statuses)
{
<li class="nav-item fs-5">
    <a class="nav-link" asp-area="" asp-controller="Home" asp-action="Index" asp-route-statusId="@status.Id">@status.StatusName</a>
</li>
}

...

//Report contents as viewed by used
@{
foreach (ReportViewModel report in Model.Reports.ReportViewModels)
{
    ...some "report" details
}

HomeController.cs (没有提到过滤列表)

        public IActionResult Index(string sortString/*, int statusId*/)
        {
            Console.Write(sortString + " " + statusId + "\n");

            var reports = from r in _myRepository.GetAllReports()
                          select r;

            ViewData["AwardSort"] = String.IsNullOrEmpty(sortString) ? "highest_award" : "";
            ViewData["UpdateSort"] = String.IsNullOrEmpty(sortString) ? "last_update" : "";

            //reports = reports.Where(r => r.StatusId == statusId); -- Need to set this and keep set

            switch (sortString)
            {
                case "last_update":
                    reports = reports.OrderBy(r => r.DateOfUpdate);
                    break;
                case "highest_award":
                    reports = reports.OrderBy(r => r.NumberOfStars);
                    break;
            }

            HallOfFameViewModel hofViewModel = new HallOfFameViewModel(_myRepository.GetTopUsers(5));
            ReportListViewModel reportsViewModel = new ReportListViewModel(
                reports.ToList(),
                _myRepository.GetUserById(_userManager.GetUserId(User))
            );

            var model = new HomePageViewModel(hofViewModel, reportsViewModel, _myRepository.GetReportStatuses());
            return View(model);
        }

//-------------------------------------------
//The filtered list would be taken here, need to somehow add currently selected sort option as well as be able to set the sorting criteria

[ResponseCache(Duration = 2)]
        [Route("Home/Index/{id}")]
        public IActionResult Index(int statusId)
        {
            var reports = from r in _nemesysRepository.GetAllReports()
                          select r;

            HallOfFameViewModel hofViewModel = new HallOfFameViewModel(_nemesysRepository.GetTopUsers(10));
            ReportListViewModel reportsViewModel = new ReportListViewModel(
                _nemesysRepository.GetAllReportsWithStatus(statusId).ToList(),
                _nemesysRepository.GetUserById(_userManager.GetUserId(User))
            );

            var model = new HomePageViewModel(hofViewModel, reportsViewModel, _nemesysRepository.GetReportStatuses());
            return View(model);
        }



提前谢谢你。

【问题讨论】:

  • 嗨,有趣,也许将排序和过滤器合并到一个模型中
  • @jspcal 我已经尝试过某种程度的东西,但在某些时候它变得完全令人费解(对 asp-net 来说非常新,几乎不知道它实际上是 3 天前)并完全放弃了它。我尝试在网上找到一些示例进行比较,但找不到任何有用的东西。

标签: html asp.net-mvc asp.net-core model


【解决方案1】:

我的朋友, 您还应该为您拥有的每个过滤器标签添加一个“CurrentFilterName”。 例如: ViewData["AwardSort"] 应该与 ViewData["CurrentAwardSort"] 结合使用 因此,当单击过滤器时页面重新加载时,您将值发送到此“FilterName” 在输入值上,您输入“CurrentFilteNameValue”。 希望这可以解决您的问题。祝你一切顺利:)

【讨论】:

  • 不明白 ViewData 如何将信息保留在当前设置的排序选项中。您能进一步解释一下吗?
【解决方案2】:

如下更改您的代码:

public IActionResult Index(string sortString,int statusId)
{
    if (statusId!=0)
    {
        reports = test.Reports.ReportViewModels.Where(a => a.Id == statusId);
        var data = HttpContext.Session.GetString("Filter");
        if(data!=null)
        {
            sortString = data;
        }
    }
    else
    {
        ViewData["AwardSort"] = String.IsNullOrEmpty(sortString) ? "highest_award" : "";
        ViewData["UpdateSort"] = String.IsNullOrEmpty(sortString) ? "last_update" : "";
        if(sortString!=null)
        {
            HttpContext.Session.SetString("Filter", sortString);
        }
    }           
    switch (sortString)
    {
        case "last_update":
            reports = reports.OrderBy(r => r.DateOfUpdate);
            break;
        case "highest_award":
            reports = reports.OrderBy(r => r.NumberOfStars);
            break;
    }
    //....

    return View(model);
}

这是我的整个工作演示:

型号:

public class Test
{
    public Report Reports { get; set; }
    public List<ReportStatus> Statuses { get; set; }
}
public class ReportStatus
{
    public int Id { get; set; }
    public string StatusName { get; set; }
}
public class Report
{
    public IEnumerable<ReportViewModel> ReportViewModels { get; set; }
}
public class ReportViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime DateOfUpdate { get; set; }
    public int NumberOfStars { get; set; }
}

查看:

@model Test
<ul class="nav nav-pills flex-column">
    <li><a asp-area="" asp-controller="Home" asp-action="Index" asp-route-sortString="@ViewData["AwardSort"]">Highest Awarded</a></li>
    <li><a asp-area="" asp-controller="Home" asp-action="Index" asp-route-sortString="@ViewData["UpdateSort"]">Last Updated</a></li>
</ul>
@foreach (ReportStatus status in Model.Statuses)
{
    <li class="nav-item fs-5">
        <a class="nav-link" asp-area="" asp-controller="Home" asp-action="Index" asp-route-statusId="@status.Id">@status.StatusName</a>
    </li>
}
<table class="table">
    <tbody>
        @foreach (ReportViewModel report in Model.Reports.ReportViewModels)
        {
            <tr>
                <td>
                    @Html.DisplayFor(model => report.DateOfUpdate)
                </td>
                <td>
                    @Html.DisplayFor(model => report.NumberOfStars)
                </td>
            </tr>
        }
    </tbody>
</table>

控制器:

public class HomeController : Controller
{
    Test test = new Test()
    {
        Reports = new Report()
        {
            ReportViewModels = new List<ReportViewModel>()
            {
                new ReportViewModel(){ Id=1, DateOfUpdate=new DateTime(2018,2,12),NumberOfStars=34},
                new ReportViewModel(){Id=1,DateOfUpdate=new DateTime(2019,3,23),NumberOfStars=23},
                new ReportViewModel(){Id=2,DateOfUpdate=new DateTime(2014,5,13),NumberOfStars=25},
                new ReportViewModel(){Id=2,DateOfUpdate=new DateTime(2015,2,24),NumberOfStars=29}
            }
        },
        Statuses= new List<ReportStatus>()
        {
            new ReportStatus(){Id=1,StatusName="aa"},
            new ReportStatus(){Id=2,StatusName="bb"}
        }
    };
    public IActionResult Index(string sortString,int statusId)
    {
        var reports = test.Reports.ReportViewModels;

        if (statusId!=0)
        {
            reports = test.Reports.ReportViewModels.Where(a => a.Id == statusId);
            var data = HttpContext.Session.GetString("Filter");
            if(data!=null)
            {
                sortString = data;
            }
        }
        else
        {
            ViewData["AwardSort"] = String.IsNullOrEmpty(sortString) ? "highest_award" : "";
            ViewData["UpdateSort"] = String.IsNullOrEmpty(sortString) ? "last_update" : "";
            if(sortString!=null)
            {
                HttpContext.Session.SetString("Filter", sortString);
            }
        }           
        switch (sortString)
        {
            case "last_update":
                reports = reports.OrderBy(r => r.DateOfUpdate);
                break;
            case "highest_award":
                reports = reports.OrderBy(r => r.NumberOfStars);
                break;
        }
        test.Reports.ReportViewModels = reports;

        return View(test);
    }
}

请务必注册 Session:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSession();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseSession();       
}

参考:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-5.0#configure-session-state

【讨论】:

  • 感谢您的详细回复,但这忽略了我的主要关注点。我有更多的订单排序按照你的建议做,没有添加它们,因为它们与问题无关。我的问题是我有按钮,显示在上面的注释“//过滤选项设置为 status.Id”下,它根据每个报告的 id 过滤我的列表。因此,如果 statusId = 1,则仅显示具有此 ID 的报告。我要问的是我也可以将当前排序选项保存到这个“过滤”列表中,并且也能够对过滤列表进行排序。我已经修改了问题以更好地展示这一点。
  • 嗨@KristianDeFilippis,您可以使用 Session 来存储最新的排序字符串。检查我更新的答案。
  • 谢谢,问题已解决!附带说明一下,由于我使用两种索引方法,第二种方法重定向过滤后的列表 ([Route("Home/Index/{id}")]),因为我无法通过&lt;a ... asp-route-statusId="@status.Id"&gt;@status.StatusName&lt;/a&gt; 发送 sortString,有没有办法通过设置 asp-route-sortString &lt;li&gt;&lt;a ... asp-route-sortString="@ViewData["sortOption"]"&gt;Sort&lt;/a&gt;&lt;/li&gt; 而留在Home/Index/{id}?对不起,如果这可能是微不足道的,我今年才开始自学编程。
  • 嗨@KristianDeFilippis,不需要使用两种方法,实际上将它们组合成一种方法会很好,否则代码会重复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
相关资源
最近更新 更多