C# 根据用户首选的列布局在 Razor 视图中创建 HTML 表

发布于 2023-02-11 15:54:42

我对如何根据用户希望查看内容的方式实现 HTML 列显示有点迷茫。

我有一个定期更新的客户信息表,我每 2 分钟用一个 ajax 请求轮询数据库以检查新记录。我最初使用拖放表来构建此功能,但是,一旦移动列,视图就会在刷新时跳跃/闪烁,这会给某些用户带来视觉困难。因此,我需要构建布局服务器端并在没有跳跃/闪烁的情况下呈现给他们。

我的截断模型是;

public class Customer
{
    public string UserId { get; set; }
    public string Name { get; set; }
    public DateTime DateJoined { get; set; }
    public string PlanName { get; set; }  
}

客户希望能够转到一个页面并在列名称旁边放置一个数字,以标识他们想要查看列的从左到右的哪个位置。基于截断视图的示例可能是;

DateJoined Name PlanName
One Two Three

或者

Name PlanName DateJoined
One Two Three

或任何其他组合

如果您有任何关于如何通过存储用户首选项然后构建视图(例如表格)来执行此操作的想法,我将不胜感激。

查看更多

1楼回答 2023-02-09

使用 CSS Grid 构建表格可以轻松地对列进行重新排序。 Stack Overflow answer 对 CSS Grid 提供的多种方法进行了很好的总结。

Razor 页面中的一个选项是使用 CSS Grid 创建表,并根据用户的列顺序首选项将类名应用于每一列。列顺序存储为每个用户的逗号分隔字符串(例如“DateJoined、Name、PlanName”),列顺序字符串中的每个段都是用户模型中属性的名称。

这是使用 CSS 网格排序和与表列关联的类名称的实现的第一遍。 Reflection(或来自here)用于使用字符串从用户模型获取属性值。

剃刀页面 (.cshtml)

<h2>Sample table</h2>

<div class="customer-table">
    <div class="col col-1">
        <span class="col-header">Col 1</span>
        <span class="col-cell">One</span>
    </div>
    <div class="col col-2">
        <span class="col-header">Col 2</span>
        <span class="col-cell">Two</span>
    </div>
    <div class="col col-3">
        <span class="col-header">Col 3</span>
        <span class="col-cell">Three</span>
    </div>
</div>

<h2>Customer tables</h2>

@foreach (Customer customer in @Model.Customers)
{
    Type type = typeof(Customer);
    string[] columnNames = customer.ColumnOrder.Split(",");
    <div class="customer-table">
        @for (int i = 0; i < columnNames.Length; i++)
        {
            string colName = columnNames[i].Trim();
            System.Reflection.PropertyInfo? propInfo = type.GetProperty(colName);
            string? propValue = propInfo?.GetValue(customer)?.ToString();
            <div class="col col-@(i+1) @colName.ToLower()">
                <span class="col-header"></span>
                <span class="col-cell">@propValue</span>
            </div>
        }
    </div>
}

剃刀页面 (.cshtml.cs)

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace WebApplication1.Pages
{
    public class Index3Model : PageModel
    {
        public List<Customer> Customers { get; set; }
        public void OnGet()
        {
            Customers = new List<Customer>()
            {
                new Customer() {
                    DateJoined = new DateOnly(2021, 4, 22),
                    Name = "Joe",
                    PlanName = "Joe's Plan",
                    UserId = "1",
                    ColumnOrder = "Name, PlanName, DateJoined"
                },
                new Customer()
                {
                    DateJoined = new DateOnly(2022, 10, 8),
                    Name = "Anne",
                    PlanName = "Anne's Plan",
                    UserId = "2",
                    ColumnOrder = "DateJoined, Name, PlanName"
                }
            };
        }
    }
}

public class Customer
{
    public string UserId { get; set; }
    public string Name { get; set; }
    public DateOnly DateJoined { get; set; }
    public string PlanName { get; set; }
    public string ColumnOrder { get; set; }
}

CSS(有多种构建表格的方法,以下不是用于演示目的的最佳作品。)

h2 {
    margin: 1rem 0;
}

.customer-table {
    display: grid;
    grid-template-areas: 'one two three';
    grid-template-columns: repeat(3, 1fr);
    width: 100%;
    margin-bottom: 2rem;
}

.col {
    display: grid;
    width: 100%;
}

.col-1 {
    grid-area: one;
}

.col-2 {
    grid-area: two;
    text-align: center;
}

.col-3 {
    grid-area: three;
    text-align: right;
}

.col-header,
.col-cell {
    border-bottom: 1px solid #d6d9dc;
    padding: .5rem;
}

.col {
    border-right: 1px solid #d6d9dc;
}

    .col:first-of-type {
        border-left: 1px solid #d6d9dc;
    }

.col-header {
    background-color: #f8f9f9;
    border-top: 1px solid #d6d9dc;
    font-weight: 700;
}

.col-cell {
    border-top: none;
}

/* --------------------------------------
    Header labels
*/

.col.name .col-header::before {
    content: "Name";
}

.col.datejoined .col-header::before {
    content: "Date Joined";
}

.col.planname .col-header::before {
    content: "Plan Name";
}
请登录后再发布答案,点击登录