ele*_*tra 8 c# blazor blazor-server-side
我有两个 Blazor 组件。第一个组件仅显示来自 JSON api 的学生列表
<select @onchange="selectStudent">
@foreach(var student in students) {
<option value="@student.id"> @student.name /option>
}
</select>
@code {
var API = "https://abcd.com/students/"
students = // variable stores JSON data of students used in the foreach loop
// sending select event to parent
[Parameter]
public EventCallBack<string> OnStudentSelect { get; set; }
public async Task SelectStudent(ChangeEventArgs e) {
await OnStudentSelect.InvokeAsync(e.Value.ToString())
}
}
Run Code Online (Sandbox Code Playgroud)
当用户从下拉列表中选择学生时,我想捕获 Student.id 并将其作为参数发送到另一个组件
@page "/student"
<Students OnStudentSelect="@GetStudentId"> </Students>
<p> Displaying profile of StudentID: @studentId </p>
<Student StudentId="@StudentId"> </Student>
@code{
private int StudentId = 1;
private void GetStudentId(int _id) {
studentId = _id
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的代码片段,但它有效,我可以看到<p></p>标签内的消息发生变化。
我遇到的问题是这样的:
<Student StudentId="StudentId"> </Student>
Run Code Online (Sandbox Code Playgroud)
由于某种原因,组件在收到新消息时不会更新StudentId
有关的文档StateHasChanged()尚不清楚,但将其放入内部Student似乎也无法解决问题。
小智 14
阅读您的帖子和评论后,我决定编写一些组件,我认为这些组件将 1. 回答您的问题,2. 向您展示将来编写 blazor 组件的好方法。让我们从第一个组件 StudentSelector.razor 开始:
StudentSelector.razor
@using BlazorAnswers.Models
@*Show loading content while students are loading*@
@if(!StudentList.Any())
{
@LoadingContent
}
else
{
<label>Select a Student: </label>
<select @onchange="HandleStudentChanged" class="form-select w-25">
@foreach (var student in StudentList)
{
<option value="@student.Id">@student.Name</option>
}
</select>
}
@code {
[Parameter] public EventCallback<StudentModel> OnStudentChanged { get; set; }
[Parameter] public IEnumerable<StudentModel> StudentList { get; set; } = Enumerable.Empty<StudentModel>();
[Parameter] public RenderFragment LoadingContent { get; set; }
/// <summary>
/// This transforms the ChangeEventArgs into a StudentModel
/// </summary>
private async Task HandleStudentChanged(ChangeEventArgs args)
{
if (OnStudentChanged.HasDelegate)
{
if (args is not null && int.TryParse((string)args.Value, out var id))
{
var selectedStudent = StudentList.FirstOrDefault(a => a.Id.Equals(id));
if (selectedStudent is not null)
await OnStudentChanged.InvokeAsync(selectedStudent);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
您应该拥有的下一个组件是显示所选学生的组件:
StudentDisplay.razor
@using BlazorAnswers.Models
@if (SelectedStudent is not null)
{
@StudentContent(SelectedStudent)
}
@code {
[Parameter] public StudentModel? SelectedStudent { get; set; }
[Parameter] public RenderFragment<StudentModel> StudentContent { get; set; } = default!;
}
Run Code Online (Sandbox Code Playgroud)
最后,所有内容都放在 Student.razor 页面中,这是一个可导航页面:
学生剃刀
@page "/student"
@using BlazorAnswers.Models
<StudentSelector OnStudentChanged="HandleStudentSelected"
StudentList="@_students">
<LoadingContent>
Loading Students...
</LoadingContent>
</StudentSelector>
@if (_selectedStudent is not null)
{
<div class="container-lg pt-4">
<StudentDisplay SelectedStudent="@_selectedStudent">
<StudentContent Context="student">
<p> Displaying profile of Id: @student.Id </p>
<p> Displaying profile of Name: @student.Name </p>
</StudentContent>
</StudentDisplay>
</div>
}
@code {
private StudentModel _selectedStudent;
private IEnumerable<StudentModel> _students = Enumerable.Empty<StudentModel>();
protected override async Task OnInitializedAsync()
{
try
{
await GetStudents();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// Method that will be invoked in the StudentSelector.razor component
/// </summary>
private void HandleStudentSelected(StudentModel selectedStudent)
{
_selectedStudent = selectedStudent;
}
/// <summary>
/// Method for retrieving students and is intentionally delayed
/// </summary>
private async Task GetStudents()
{
await Task.Delay(3000);
_students = _selectableStudents;
}
/// <summary>
/// Test Data to use as an example
/// </summary>
private static IEnumerable<StudentModel> _selectableStudents = new List<StudentModel>()
{
new StudentModel{ Id = 1, Name = "Joe" },
new StudentModel{ Id = 2, Name = "Amy" },
new StudentModel{ Id = 3, Name = "Beth" },
new StudentModel{ Id = 4, Name = "Kevin" },
new StudentModel{ Id = 5, Name = "Carl" },
new StudentModel{ Id = 6, Name = "Chad" },
new StudentModel{ Id = 7, Name = "Bryan" },
new StudentModel{ Id = 8, Name = "Kelly" },
new StudentModel{ Id = 9, Name = "Steve" },
new StudentModel{ Id = 10, Name = "Doug" },
};
}
Run Code Online (Sandbox Code Playgroud)
然后是 StudentModel 类:
StudentModel.cs
public class StudentModel
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}
Run Code Online (Sandbox Code Playgroud)
设计 blazor 应用程序时要考虑的另一件事是让组件保持愚蠢而页面保持智能。这意味着当注入服务时,尝试将它们保留在页面中,而不是让它们进入组件本身。这避免了很多复杂的情况,并允许您构建可重用的组件。我知道有人说过关于调用 StateHasChanged 的事情,但仅当 UI 因非人类交互而发生更改时才尝试使用它。
| 归档时间: |
|
| 查看次数: |
14203 次 |
| 最近记录: |