在 Razor Class 库控件中的事件之间保留数据

Persisting data between events in Razor Class Library control

我正在尝试创建一个 Razor Class 库 (RCL),然后我可以将其用作我的 Blazor Server 应用程序中的一组可重用控件。 RCL 控件是一个 table,包括分页和列排序。控件的数据流是 Blazor 应用程序处理所有数据请求,然后将数据传递给 RCL 控件。 RCL 控件处理 UI 事件(next/previous 分页)和记录的显示。我遇到的问题是当前页面计数(当用户单击下一页或上一页时会更新)不会在事件之间持续存在,因此计数永远不会改变。我如何跨事件保留数据(我希望在 RCL 控件中跟踪 ui 事件,而不是在使用该控件的 Blazor 应用程序中)。这是我的代码(缩写):

Razor Class 图书馆控制:

@if (employeeModels == null)
{
    <p><em>Loading...</em></p>
}
else
{
   //table with data ...
   //controls to handle pagination
   <div class="pagination">
    <button class="btn btn-custom" @onclick=@(async ()=>await NavigateToPage("previous"))>Prev</button>
    @for (int i = startPage; i <= endPage; i++)
    {
        var currentPage = i;
        <button class="btn btn-custom pagebutton @(currentPage==curPage?"btn-danger":"")" @onclick=@(async () =>await refreshRecords(currentPage))>
            @currentPage
        </button>
    }
    <button class="btn btn-custom" @onclick=@(async ()=>await NavigateToPage("next"))>Next</button>
</div>
}
@code {
    [Parameter]
    public List<EmployeesModel> employeeModels { get; set; }
    [Parameter]
    public EventCallback<bool> RefreshDataEvent { get; set; }
    int totalPages;
    int totalRecords;
    [Parameter]
    public int TotalNumRecords { get; set; }
    [Parameter]
    public int curPage { get; set; }
    [Parameter]
    public int pagerSize{ get; set; }
    [Parameter]
    public int pageSize { get; set; }
    int startPage;
    int endPage;
    [Parameter]
    public string sortColumnName { get; set; } = "LastName";
    [Parameter]
    public string sortDir { get; set; } = "DESC";

    protected override void OnParametersSet()
    {

        base.OnParametersSet();
        totalRecords = TotalNumRecords;
        totalPages = (int)Math.Ceiling(totalRecords / (decimal)pageSize);
        SetPagerSize("forward");        
    }
    public async Task refreshRecords(int currentPage)
    { 
        curPage = currentPage;
        await RefreshDataEvent.InvokeAsync(true);
        this.StateHasChanged();
    }
    public void SetPagerSize(string direction)
    {
        if (direction == "forward" && endPage < totalPages)
        {
            startPage = endPage + 1;
            if (endPage + pagerSize < totalPages)
            {
                endPage = startPage + pagerSize - 1;
            }
            else
            {
                endPage = totalPages;
            }
            this.StateHasChanged();
        }
        else if (direction == "back" && startPage > 1)
        {
            endPage = startPage - 1;
            startPage = startPage - pagerSize;
        }
    }
    public async Task NavigateToPage(string direction)
    {
        if (direction == "next")
        {
            if (curPage < totalPages)
            {
                if (curPage == endPage)
                {
                    SetPagerSize("forward");
                }
                curPage += 1;
            }
        }
        else if (direction == "previous")
        {
            if (curPage > 1)
            {
                if (curPage == startPage)
                {
                    SetPagerSize("back");
                }
                curPage -= 1;
            }
        }    
        await refreshRecords(curPage);
    }
}

Blazor 应用程序使用控件:

<SortablePaginatedEmployeeTable  
    employeeModels="@employees" 
    curPage="@paginationCurrentPage" 
    pageSize="@paginationPageSize" 
    pagerSize="@paginationPagerSize" 
    sortColumnName="@paginationSortColumnName" 
    sortDir="@paginationSortDirection" 
    RefreshDataEvent="EmployeeListRefrshed" 
    @ref="EmployeeTableControl" 
    TotalNumRecords="@totalNumbEmployees" 
    GotToPageEven="EmployeeNextClick"  >
</SortablePaginatedEmployeeTable>

@code {
    private SortablePaginatedEmployeeTable EmployeeTableControl;
    int paginationCurrentPage = 1;
    int paginationPageSize = 3;
    int paginationPagerSize = 3;
    string paginationSortColumnName = "LastName";
    string paginationSortDirection = "Desc";
    int totalNumbEmployees = 0;

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        await EmployeeListRefrshed();
    }
    
    private async Task EmployeeListRefrshed()
    {
        all_employees = await _db.ListAllEmployees((EmployeeTableControl.curPage - 1) * paginationPageSize, paginationPageSize, paginationSortColumnName, paginationSortDirection);
        totalNumbEmployees = _db.CountNumberEmployees();
        foreach(var e in all_employees)
        {
            employees.Add(new EmployeesModel { Email = e.Email, FirstName = e.FirstName, LastName = e.LastName, Id = e.Id, PhoneNumber = e.PhoneNumber });
        }
    }

}

使用此代码,当用户单击“下一步”时,将调用 NavigateToPage 函数,但它总是 returns 2. 我认为这是因为数据在按下按钮之间没有持续存在?我该如何解决?

您的问题在于更新组件中的 Parameter。它基本上是一个NONO。阅读它们,使用它们,但永远不要修改它们。

当您触发 RefreshDataEvent 时,它会调用获取数据的 EmployeeListRefrshed。这会更新 employees。当 EmployeeListRefrshed 完成组件时 re-renders。这包括触发 SortablePaginatedEmployeeTable 的 re-render。 paginationCurrentPage 仍设置为 1,因此第 1 页上的组件 re-renders。

您需要执行以下操作:

组件

[Parameter]
    public EventCallback<int> RefreshDataEvent { get; set; }

    public async Task refreshRecords(int currentPage)
    { 
        await RefreshDataEvent.InvokeAsync(currentPage);
        // probably not needed
        this.StateHasChanged();
    }

    
    private async Task EmployeeListRefrshed(int pageNo)
    {
        all_employees = await _db.ListAllEmployees((pageNo - 1) * paginationPageSize, paginationPageSize, paginationSortColumnName, paginationSortDirection);
        totalNumbEmployees = _db.CountNumberEmployees();
        foreach(var e in all_employees)
        {
            employees.Add(new EmployeesModel { Email = e.Email, FirstName = e.FirstName, LastName = e.LastName, Id = e.Id, PhoneNumber = e.PhoneNumber });
        }
        this.pagingationcurrentpage = pageNo 
    }