1 准备工作
继续使用上一章项目。
本章展示如何组合Razor组件来创建更复杂的特性。展示如何创建组件之间的父子关系,如何利用属性配置组件,以及如何创建自定义事件,以在发生重要更改时发出信号。还展示了组件如何从父组件接收内容,以及如何使用模板组件一致地生成内容,模板组件可以用一个或多个泛型类型参数定义。在本章结束时,演示了 Blazor应用程序如何对连接和应用程序错误做出反应。
2 结合组件
Blazor 组件可以组合起来创建更复杂的功能。Blazor 文件夹中添加 SelectFilter.razor:
<div class="form-group">
<label for="select-@Title">@Title</label>
<select name="select-@Title" class="form-control" @bind="SelectedValue">
<option disabled selected>Select @Title</option>
@foreach (string val in Values)
{
<option value="@val" selected="@(val == SelectedValue)">
@val
</option>
}
</select>
</div>
@code
{
public IEnumerable<string> Values { get; set; } = Enumerable.Empty<string>();
public string SelectedValue { get; set; }
public string Title { get; set; } = "Placeholder";
}
该组件呈现现一个 selcect 元素,该元素允许用户选择城市。在 Blazor 文件夹的 PeopleList.razor 中应用此组件替换现有的 select:
<SelectFilter />
当组件添加到控制器视图或 Razor Pages 所呈现的内容中时,就会使用组件元素,当一个组件添加到另一个组件所呈现的内容中时,该组件的名称将用作一个元素。本例向 PeopleList 组件所呈现的内容添加了 SelectFilter 组件,使用 SelectFilter 元素来实现,大小写必须匹配。
组合组件时,效果是一个组件将其部分布局的职责委托给另一个组件。本例各组成部分构成父/子关系:PcopleList 组件是父组件,SelectFilter 组件是子组件。
请求http:/localhost:5000/controllers
查看效果。
2.1 利用属性配置组件
使用 SelectList 组件的目标是创建一个可在整个应用程序中使用的通用特性,配置每次使用它时显示的值。Razor 组件是用属性配置的,这些属性添加到应用它们的 HTML 元素中。分配给 HTML 元素属性的值被分配给组件的 C# 属性。Parameter 属性应用于组件允许配置的 C# 属性, 在 Blazor 文件夹的 SelectFilter.razor 文件中声明可配置属性如下:
@code
{
[Parameter]
public IEnumerable<string> Values { get; set; } = Enumerable.Empty<string>();
public string SelectedValue { get; set; }
[Parameter]
public string Title { get; set; } = "Placeholder";
}
组件可以选择它们允许配置的属性。在本例中,Parameter属性已应用于 SelectFilter 组件定义的两个属性。在 Blazor 文件夹的 PeopleList.razor ,修改了组件用于应用 SelectFilter 组件以添加配置属性的元素,如下:
<SelectFilter values="@Cities" title="city" />
对于每个应该配置的属性,将一个同名属性添加到父元素的 HTML 元素中。属性值可以是固定的值,比如分配给 title 属性的 City 字符串,也可以是 Razor 表达式,如 @Cities (它将 City 属性中的对象序列分配给 values 属性)。
1.设置和接收批量配置设置
如果存在许多配置设置,可以指定一个属性来接收没有被其他属性匹配的任何属性值,然后可将其作为一个集合应用。如下在 Blazor 文件夹的 SelectFiter.razor 文件中接收未匹配属性:
<select name="select-@Title" class="form-control" @bind="SelectedValue"
@attributes="Attrs">
......
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> Attrs { get; set; }
将 Parameter 属性的 CaptureUnmatchedValues 参数设置为 true,将标识一个属性作为未以其他方式匹配的属性的集合。属性的类型必须是 Dictionary<string,object>,这表示属性名称和值,可以使用@attribute 表达式应用于元素。它允许一次性应用一组属性,上面更改的效果意味着 SelectFilter 组件接收 Values 和 Title 属性值,其他任何属性都分配给 Attrs 属性并传递给 select 元素。
在 Blazor 文件夹的 PeopleList.razor 文件中添加元素属性:
<SelectFilter values="@Cities" title="city" autofocus="true" name="city"
required ="true"/>
请求 http://localhost:5000/controllers
。传递给 select 元素的属性不影响显示,右击选择元素,并从弹出菜单中选择检查,就将看到属性添加到 PeopleList 组件的 SelectFilter 元素中,SelectFilter 元素已添加到 SelectFilter 组件呈现的元素中。
2.在控制器视图或 Razor Pages 中配置组件
当使用组件元素应用组件时,属性还用于配置组件。在 Blazor 文件夹的 PeopleList.razor,向 PeopleList 组件添加了属性,该属性指定应该显示来自数据库的多少项,以及将传递给 SelectFilter 组件的字符串值,如下:
<SelectFilter values="@Cities" title="@SelectTitle" />
@code
{
[Inject]
public DataContext Context { get; set; }
public IEnumerable<Person> People => Context.People
.Include(p => p.Department).Include(p => p.Location)
.Take(ItemCount);
public IEnumerable<string> Cities => Context.Locations.Select(l => l.City);
public string SelectedCity { get; set; }
public string GetClass(string city) =>
SelectedCity == city ? "bg-info text-white" : "";
[Parameter]
public int ItemCount { get; set; } = 4;
[Parameter]
public string SelectTitle { get; set; }
}
C#属性的值是通过将名称以param-开头、后跟属性名称的属性添加到组件元素来提供的,在 Views/Home 文件夹的 Index.cshtm 文件中添加配置属性如下:
<component type="typeof(MyAdvan