自动刷新 Blazor 中的组件
Automatically refresh a component in Blazor
我正在处理用于添加新对象的 Blazor 页面。对象 "RepairOrder" 具有对象列表 "RepairSection"。
页面上有一个区域将循环遍历列表 "RepairOrder"。"RepairSections" 并显示元素:
<div class="col-lg-10">
@if (sections.Count > 0)
{
foreach (var sec in sections)
{
<h3>Section @sec.SectionNumber</h3>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-5">
<label for="Failure" class="control-label">Failure: </label>
<input for="Failure" class="form-control" bind="@sec.Failure" readonly />
</div>
<div class="col-lg-1"></div>
<div class="col-lg-1">
<label><input type="checkbox" checked="@IsCApprovedChecked(sec)" /> Warranty</label>
</div>
<div class="col-lg-2">
<label><input type="checkbox" value="@IsWarrantyChecked(sec)" /> Repair Approved</label>
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="AdminComments" class="control-label">Admin Comments: </label>
<input for="AdminComments" class="form-control" bind="@sec.AdminComments" readonly />
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="TechComments" class="control-label">Tech Comments: </label>
<input for="TechComments" class="form-control" bind="@sec.TechComments" readonly />
</div>
</div>
}
}
</div>
列表中的所有当前栏目都添加到页面后,有一个按钮可以添加新栏目。单击按钮时,该函数将布尔值更改为 true 以将模态作为对话框打开。模态包含用于输入新部分元素的字段。
打开模式调用的函数:
protected void AddSectionCalled()
{
_newSection = new RepairSection();
this.isAddNew = true;
}
模态代码:
<div class="modal" tabindex="-1" style="display:block" role="dialog">
<div class="modal-dialog modal-dialog-scrollable modal-xl">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">New Repair Section</h3>
<button type="button" class="close" onclick="@CloseModal"><span aria-hidden="true">X</span></button>
</div>
<div class="modal-body">
<form>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-2">
<label for="sectionLetter" class="control-label">Section: </label>
<input for="sectionLetter" class="form-control" bind="@_newSection.SectionNumber" />
</div>
<div class="col-lg-1"></div>
<div class="col-lg-2">
<label><input type="checkbox" bind="@_newSection.Warranty" /> Warranty</label>
</div>
<div class="col-lg-2">
<label><input type="checkbox" bind="@_newSection.CustomerApproved" /> Repair Approved</label>
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_failure" class="control-label">Failure: </label>
<input for="_failure" class="form-control" bind="@_newSection.Failure"/>
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_adminComments" class="control-label">Admin Comments: </label>
<input for="_adminComments" class="form-control" bind="@_newSection.AdminComments" />
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_techComments" class="control-label">Tech Comments: </label>
<input for="_techComments" class="form-control" bind="@_newSection.TechComments"/>
</div>
</div>
<br/>
<button class="btn btn-primary float-left" onclick="AddNewSection">Add New Section</button>
</form>
</div>
</div>
</div>
</div>
单击 "Add New Section" 按钮时,根据模态中收集的信息创建的“_newSection”对象将添加到 "sections" 最初在页面加载时循环的列表中。
private void AddNewSection()
{
sections.Add(_newSection);
this.StateHasChanged();
this.isAddNew = false;
}
如您所见,我在新部分添加到部分列表后添加了 "StateHasChanged()"。但是,页面不会呈现以显示新部分。
我最初在页面 "OnInitAsync()" 事件上创建了虚拟数据,该事件在显示数据之前加载了部分列表。这样我就可以确保页面正确显示列表中的内容。
如何在用户向列表中添加新对象后让页面重新呈现列表中的信息?
----编辑-----
下面是整个页面的代码。我会尽量在周末尽量减少这种情况,但是这里真的没有很多。
@page "/AddRepairOrder"
@using ShopLiveWebVersion2._0.Models
@using ShopLiveWebVersion2._0.DataAccess
@using ShopLiveWebVersion2._0.Services
@using ShopLiveWebVersion2._0.Data
@inject IUriHelper UriHelper
@inject RepairOrderContext context
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10"><h1>Create New Repair Order</h1></div>
</div>
<br /><br />
<form id="AddROForm">
<div class="form-group">
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-2">
<label for="ControlNumber" class="control-label">Repair Order #: </label>
<input for="ControlNumber" class="form-control" bind="@ro.ControlNumber" maxlength="15" required />
</div>
<div class="col-lg-1">
<label for="TagNumber" class="control-label">Tag #: </label>
<input for="TagNumber" class="form-control" bind="@ro.TagNumber" maxlength="8" />
</div>
<div class="col-lg-3">
<label for="VIN" class="control-label">VIN: </label>
<input for="VIN" class="form-control" bind="@ro.VIN" maxlength="18" />
@*<small id="Chasis" class="form-text text-muted">@ro.GetChassisNumber()</small> figure out how to get chassis from vin after box looses focus*@
</div>
<div class="col-lg-2">
<label for="Make" class="control-label">Make: </label>
<input for="Make" class="form-control" bind="@ro.Make" maxlength="30" />
</div>
<div class="col-lg-2">
<label for="Madel" class="control-label">Model: </label>
<input for="Madel" class="form-control" bind="@ro.Madel" maxlength="30" />
</div>
</div>
<div class="row AddRow">
<div class="col-lg-1"></div>
<div class="col-lg-4">
<label for="Customer" class="control-label">Customer: </label>
<input for="Custoemr" class="form-control" bind="@ro.Customer" maxlength="50" />
</div>
<div class="col-lg-2">
<label asp-for="Location" class="control-label">Vehicle Location: </label>
<select asp-for="Location" class="form-control" bind="@ro.Location">
<option value="">-- Select a Location --</option>
@foreach (var loc in Location)
{
<option value="@loc">@loc</option>
}
</select>
</div>
<div class="col-lg-2">
<label asp-for="Assigned" class="control-label">Assigned: </label>
<select asp-for="Assigned" class="form-control" bind="@ro.Assigned">
<option value="">-- Select an Employee --</option>
@foreach (var emp in Employee)
{
<option value="@emp">@emp</option>
}
</select>
</div>
<div class="col-lg-2">
<label asp-for="Status" class="control-label">Status: </label>
<select asp-for="Status" class="form-control" bind="@ro.Status">
<option value="">-- Select a Status --</option>
@foreach (var st in Status)
{
<option value="@st">@st</option>
}
</select>
</div>
</div>
<br />
<div class="row"><div class="col-lg-1"></div><div class="col-lg-10"><hr id="Double" /></div></div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
@if (sections.Count > 0)
{
foreach (var sec in sections)
{
<h3>Section @sec.SectionNumber</h3>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-5">
<label for="Failure" class="control-label">Failure: </label>
<input for="Failure" class="form-control" bind="@sec.Failure" readonly />
</div>
<div class="col-lg-1"></div>
<div class="col-lg-1">
<label><input type="checkbox" checked="@IsCApprovedChecked(sec)" /> Warranty</label>
</div>
<div class="col-lg-2">
<label><input type="checkbox" value="@IsWarrantyChecked(sec)" /> Repair Approved</label>
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="AdminComments" class="control-label">Admin Comments: </label>
<input for="AdminComments" class="form-control" bind="@sec.AdminComments" readonly />
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="TechComments" class="control-label">Tech Comments: </label>
<input for="TechComments" class="form-control" bind="@sec.TechComments" readonly />
</div>
</div>
}
}
</div>
</div>
<div class="row"></div>
</div> @*Form-group*@
</form>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-9">
<br /><br />
<button class="btn btn-primary float-right" onclick="@AddSectionCalled">Add New Section</button>
</div>
</div>
@if (isAddNew == true)
{
<div class="modal" tabindex="-1" style="display:block" role="dialog">
<div class="modal-dialog modal-dialog-scrollable modal-xl">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">New Repair Section</h3>
<button type="button" class="close" onclick="@CloseModal"><span aria-hidden="true">X</span></button>
</div>
<div class="modal-body">
<form>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-2">
<label for="sectionLetter" class="control-label">Section: </label>
<input for="sectionLetter" class="form-control" bind="@_newSection.SectionNumber" />
</div>
<div class="col-lg-1"></div>
<div class="col-lg-2">
<label><input type="checkbox" bind="@_newSection.Warranty" /> Warranty</label>
</div>
<div class="col-lg-2">
<label><input type="checkbox" bind="@_newSection.CustomerApproved" /> Repair Approved</label>
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_failure" class="control-label">Failure: </label>
<input for="_failure" class="form-control" bind="@_newSection.Failure" />
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_adminComments" class="control-label">Admin Comments: </label>
<input for="_adminComments" class="form-control" bind="@_newSection.AdminComments" />
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_techComments" class="control-label">Tech Comments: </label>
<input for="_techComments" class="form-control" bind="@_newSection.TechComments" />
</div>
</div>
<br />
<button class="btn btn-primary float-left" onclick="AddNewSection()">Add New Section</button>
</form>
</div>
</div>
</div>
</div>
}
@functions
{
private RepairOrder ro;
private RepairOrder incomingRO;
private RepairOrderDataAccess RoData;
private string chassis;
private List<string> Location;
private List<string> Employee;
private List<string> Status;
private FileService fileService;
private List<RepairSection> sections;
private bool isAddNew;
//for new repair section modal
private RepairSection _newSection;
protected override async Task OnInitAsync()
{
ro = new RepairOrder();
Location = new List<string>();
Employee = new List<string>();
Status = new List<string>();
sections = new List<RepairSection>();
isAddNew = false;
fileService = new FileService();
RoData = new RepairOrderDataAccess(context);
await LoadData();
}
private async Task LoadData()
{
Location = await Task.Run(() => fileService.ReadLocation());
Employee = await Task.Run(() => fileService.ReadEmployees());
Status = await Task.Run(() => fileService.ReadStatus());
}
public string IsCApprovedChecked(RepairSection sc)
{
if (sc.CustomerApproved == true)
{
return "checked";
}
else
{
return "";
}
}
public string IsWarrantyChecked(RepairSection sc)
{
if (sc.Warranty == true)
{
return "checked";
}
else
{
return "";
}
}
protected void AddSectionCalled()
{
_newSection = new RepairSection();
this.isAddNew = true;
}
private void AddNewSection()
{
sections.Add(_newSection);
this.StateHasChanged();
this.isAddNew = false;
}
private void CloseModal()
{
this.isAddNew = false;
}
您在模式窗体上绑定按钮的 onclick
事件的方式有问题。
你有 onclick="AddNewSection()"
- 以这种方式编写它可能会被解释为纯 javascript 调用,如果您在浏览器工具中检查 DOM,您可能会在按钮上看到 onclick="AddNewSection()"
。
你应该onclick="@AddNewSection"
- 这样,Blazor 会将 onclick
事件连接到您的 C# 方法。
我正在处理用于添加新对象的 Blazor 页面。对象 "RepairOrder" 具有对象列表 "RepairSection"。
页面上有一个区域将循环遍历列表 "RepairOrder"。"RepairSections" 并显示元素:
<div class="col-lg-10">
@if (sections.Count > 0)
{
foreach (var sec in sections)
{
<h3>Section @sec.SectionNumber</h3>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-5">
<label for="Failure" class="control-label">Failure: </label>
<input for="Failure" class="form-control" bind="@sec.Failure" readonly />
</div>
<div class="col-lg-1"></div>
<div class="col-lg-1">
<label><input type="checkbox" checked="@IsCApprovedChecked(sec)" /> Warranty</label>
</div>
<div class="col-lg-2">
<label><input type="checkbox" value="@IsWarrantyChecked(sec)" /> Repair Approved</label>
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="AdminComments" class="control-label">Admin Comments: </label>
<input for="AdminComments" class="form-control" bind="@sec.AdminComments" readonly />
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="TechComments" class="control-label">Tech Comments: </label>
<input for="TechComments" class="form-control" bind="@sec.TechComments" readonly />
</div>
</div>
}
}
</div>
列表中的所有当前栏目都添加到页面后,有一个按钮可以添加新栏目。单击按钮时,该函数将布尔值更改为 true 以将模态作为对话框打开。模态包含用于输入新部分元素的字段。
打开模式调用的函数:
protected void AddSectionCalled()
{
_newSection = new RepairSection();
this.isAddNew = true;
}
模态代码:
<div class="modal" tabindex="-1" style="display:block" role="dialog">
<div class="modal-dialog modal-dialog-scrollable modal-xl">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">New Repair Section</h3>
<button type="button" class="close" onclick="@CloseModal"><span aria-hidden="true">X</span></button>
</div>
<div class="modal-body">
<form>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-2">
<label for="sectionLetter" class="control-label">Section: </label>
<input for="sectionLetter" class="form-control" bind="@_newSection.SectionNumber" />
</div>
<div class="col-lg-1"></div>
<div class="col-lg-2">
<label><input type="checkbox" bind="@_newSection.Warranty" /> Warranty</label>
</div>
<div class="col-lg-2">
<label><input type="checkbox" bind="@_newSection.CustomerApproved" /> Repair Approved</label>
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_failure" class="control-label">Failure: </label>
<input for="_failure" class="form-control" bind="@_newSection.Failure"/>
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_adminComments" class="control-label">Admin Comments: </label>
<input for="_adminComments" class="form-control" bind="@_newSection.AdminComments" />
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_techComments" class="control-label">Tech Comments: </label>
<input for="_techComments" class="form-control" bind="@_newSection.TechComments"/>
</div>
</div>
<br/>
<button class="btn btn-primary float-left" onclick="AddNewSection">Add New Section</button>
</form>
</div>
</div>
</div>
</div>
单击 "Add New Section" 按钮时,根据模态中收集的信息创建的“_newSection”对象将添加到 "sections" 最初在页面加载时循环的列表中。
private void AddNewSection()
{
sections.Add(_newSection);
this.StateHasChanged();
this.isAddNew = false;
}
如您所见,我在新部分添加到部分列表后添加了 "StateHasChanged()"。但是,页面不会呈现以显示新部分。
我最初在页面 "OnInitAsync()" 事件上创建了虚拟数据,该事件在显示数据之前加载了部分列表。这样我就可以确保页面正确显示列表中的内容。
如何在用户向列表中添加新对象后让页面重新呈现列表中的信息?
----编辑-----
下面是整个页面的代码。我会尽量在周末尽量减少这种情况,但是这里真的没有很多。
@page "/AddRepairOrder"
@using ShopLiveWebVersion2._0.Models
@using ShopLiveWebVersion2._0.DataAccess
@using ShopLiveWebVersion2._0.Services
@using ShopLiveWebVersion2._0.Data
@inject IUriHelper UriHelper
@inject RepairOrderContext context
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10"><h1>Create New Repair Order</h1></div>
</div>
<br /><br />
<form id="AddROForm">
<div class="form-group">
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-2">
<label for="ControlNumber" class="control-label">Repair Order #: </label>
<input for="ControlNumber" class="form-control" bind="@ro.ControlNumber" maxlength="15" required />
</div>
<div class="col-lg-1">
<label for="TagNumber" class="control-label">Tag #: </label>
<input for="TagNumber" class="form-control" bind="@ro.TagNumber" maxlength="8" />
</div>
<div class="col-lg-3">
<label for="VIN" class="control-label">VIN: </label>
<input for="VIN" class="form-control" bind="@ro.VIN" maxlength="18" />
@*<small id="Chasis" class="form-text text-muted">@ro.GetChassisNumber()</small> figure out how to get chassis from vin after box looses focus*@
</div>
<div class="col-lg-2">
<label for="Make" class="control-label">Make: </label>
<input for="Make" class="form-control" bind="@ro.Make" maxlength="30" />
</div>
<div class="col-lg-2">
<label for="Madel" class="control-label">Model: </label>
<input for="Madel" class="form-control" bind="@ro.Madel" maxlength="30" />
</div>
</div>
<div class="row AddRow">
<div class="col-lg-1"></div>
<div class="col-lg-4">
<label for="Customer" class="control-label">Customer: </label>
<input for="Custoemr" class="form-control" bind="@ro.Customer" maxlength="50" />
</div>
<div class="col-lg-2">
<label asp-for="Location" class="control-label">Vehicle Location: </label>
<select asp-for="Location" class="form-control" bind="@ro.Location">
<option value="">-- Select a Location --</option>
@foreach (var loc in Location)
{
<option value="@loc">@loc</option>
}
</select>
</div>
<div class="col-lg-2">
<label asp-for="Assigned" class="control-label">Assigned: </label>
<select asp-for="Assigned" class="form-control" bind="@ro.Assigned">
<option value="">-- Select an Employee --</option>
@foreach (var emp in Employee)
{
<option value="@emp">@emp</option>
}
</select>
</div>
<div class="col-lg-2">
<label asp-for="Status" class="control-label">Status: </label>
<select asp-for="Status" class="form-control" bind="@ro.Status">
<option value="">-- Select a Status --</option>
@foreach (var st in Status)
{
<option value="@st">@st</option>
}
</select>
</div>
</div>
<br />
<div class="row"><div class="col-lg-1"></div><div class="col-lg-10"><hr id="Double" /></div></div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
@if (sections.Count > 0)
{
foreach (var sec in sections)
{
<h3>Section @sec.SectionNumber</h3>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-5">
<label for="Failure" class="control-label">Failure: </label>
<input for="Failure" class="form-control" bind="@sec.Failure" readonly />
</div>
<div class="col-lg-1"></div>
<div class="col-lg-1">
<label><input type="checkbox" checked="@IsCApprovedChecked(sec)" /> Warranty</label>
</div>
<div class="col-lg-2">
<label><input type="checkbox" value="@IsWarrantyChecked(sec)" /> Repair Approved</label>
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="AdminComments" class="control-label">Admin Comments: </label>
<input for="AdminComments" class="form-control" bind="@sec.AdminComments" readonly />
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="TechComments" class="control-label">Tech Comments: </label>
<input for="TechComments" class="form-control" bind="@sec.TechComments" readonly />
</div>
</div>
}
}
</div>
</div>
<div class="row"></div>
</div> @*Form-group*@
</form>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-9">
<br /><br />
<button class="btn btn-primary float-right" onclick="@AddSectionCalled">Add New Section</button>
</div>
</div>
@if (isAddNew == true)
{
<div class="modal" tabindex="-1" style="display:block" role="dialog">
<div class="modal-dialog modal-dialog-scrollable modal-xl">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">New Repair Section</h3>
<button type="button" class="close" onclick="@CloseModal"><span aria-hidden="true">X</span></button>
</div>
<div class="modal-body">
<form>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-2">
<label for="sectionLetter" class="control-label">Section: </label>
<input for="sectionLetter" class="form-control" bind="@_newSection.SectionNumber" />
</div>
<div class="col-lg-1"></div>
<div class="col-lg-2">
<label><input type="checkbox" bind="@_newSection.Warranty" /> Warranty</label>
</div>
<div class="col-lg-2">
<label><input type="checkbox" bind="@_newSection.CustomerApproved" /> Repair Approved</label>
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_failure" class="control-label">Failure: </label>
<input for="_failure" class="form-control" bind="@_newSection.Failure" />
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_adminComments" class="control-label">Admin Comments: </label>
<input for="_adminComments" class="form-control" bind="@_newSection.AdminComments" />
</div>
</div>
<div class="row">
<div class="col-lg-1"></div>
<div class="col-lg-10">
<label for="_techComments" class="control-label">Tech Comments: </label>
<input for="_techComments" class="form-control" bind="@_newSection.TechComments" />
</div>
</div>
<br />
<button class="btn btn-primary float-left" onclick="AddNewSection()">Add New Section</button>
</form>
</div>
</div>
</div>
</div>
}
@functions
{
private RepairOrder ro;
private RepairOrder incomingRO;
private RepairOrderDataAccess RoData;
private string chassis;
private List<string> Location;
private List<string> Employee;
private List<string> Status;
private FileService fileService;
private List<RepairSection> sections;
private bool isAddNew;
//for new repair section modal
private RepairSection _newSection;
protected override async Task OnInitAsync()
{
ro = new RepairOrder();
Location = new List<string>();
Employee = new List<string>();
Status = new List<string>();
sections = new List<RepairSection>();
isAddNew = false;
fileService = new FileService();
RoData = new RepairOrderDataAccess(context);
await LoadData();
}
private async Task LoadData()
{
Location = await Task.Run(() => fileService.ReadLocation());
Employee = await Task.Run(() => fileService.ReadEmployees());
Status = await Task.Run(() => fileService.ReadStatus());
}
public string IsCApprovedChecked(RepairSection sc)
{
if (sc.CustomerApproved == true)
{
return "checked";
}
else
{
return "";
}
}
public string IsWarrantyChecked(RepairSection sc)
{
if (sc.Warranty == true)
{
return "checked";
}
else
{
return "";
}
}
protected void AddSectionCalled()
{
_newSection = new RepairSection();
this.isAddNew = true;
}
private void AddNewSection()
{
sections.Add(_newSection);
this.StateHasChanged();
this.isAddNew = false;
}
private void CloseModal()
{
this.isAddNew = false;
}
您在模式窗体上绑定按钮的 onclick
事件的方式有问题。
你有 onclick="AddNewSection()"
- 以这种方式编写它可能会被解释为纯 javascript 调用,如果您在浏览器工具中检查 DOM,您可能会在按钮上看到 onclick="AddNewSection()"
。
你应该onclick="@AddNewSection"
- 这样,Blazor 会将 onclick
事件连接到您的 C# 方法。