在 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
}
我正在尝试创建一个 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
}