不是全文翻译,部分翻译自认为可能不准确,就原文照搬了。
创建一个 Blazor TabControl 组件,有两个目标知识点:
- Pass data into a RenderFragment to give it context.
- Use a CascadingParameter to pass the parent TabControl component into its child TabPage components.
下面看最终效果图:
实操开始:
请先创建一个 Blazor 项目(Blazor Client 或者 Server 皆可,我们以 Blazor Server 为例),
第一步,创建两个组件:TabControl
和TabPage
。TabPage
组件有一个父TabControl
属性引用(属性名Parent
,添加CascadingParameter
特性)。
TabControl 组件:
文件路径:./Shared/TabControl.razor
<div>这是一个TabControl</div>
<CascadingValue Value="this"> @ChildContent </CascadingValue>
@code { // 如果我们想以<TabPage
>标签的形式使用TabPage,那么下面的代码是必须的 [Parameter] public
RenderFragment? ChildContent { get; set; } }</TabPage
>
TabPage 组件:
文件路径:./Shared/TabPage.razor
<div>这是一个TabPage</div>
@ChildContent @code { [CascadingParameter] private TabControl? Parent { get;
set; } [Parameter] public RenderFragment? ChildContent { get; set; } protected
override void OnInitialized() { if (Parent == null) throw new
ArgumentNullException(nameof(Parent), "TabPage必须包含TabControl引用");
base.OnInitialized(); } }
TabControl 关联 TabPage
在TabPage
的OnInitialized
方法中添加下面这一行代码,使TabPage
关联上TabControl
:
Parent.AddPage(this);
AddPage
方法见下面的代码,在TabControl
调用AddPage
方法保存引用后,我们在TabControl
中添加ActivePage
属性,同样看下面的代码:
public TabPage? ActivePage { get; set; }
readonly List<TabPage> _pages = new();
internal void AddPage(TabPage tabPage)
{
_pages.Add(tabPage);
if (_pages.Count == 1)
ActivePage = tabPage;
StateHasChanged();
}
给AddPage
组件添加一个Text
属性用于展示。
[Parameter]
public string? Text { get; set; }
在TabControl
中添加以下标签(在ChildContent
渲染之前),这些标签会一次性全部渲染出来,当点击某个TabPage
时会改变TabControl
的选择项。
<div class="btn-group" role="group">
@foreach (TabPage tabPage in Pages)
{
<button type="button"
class="btn @GetButtonClass(tabPage)"
@onclick=@( ()=>ActivatePage(tabPage) )>
@tabPage.Text
</button>
}
</div>
上面这些标签会创建标准的 Bootstrap 按钮组,每个TabPage
会创建一个有以下特征的按钮:
- CSS 类设置为"btn",并通过
GetButtonClass
方法追加 CSS 类名,如果当前TabPage
为ActivePage
,添加 CSS 类btn-primary
,否则添加btn-secondary
。 - 当点击按钮时会激活点击的
TabPage
。
注意:@onclick
需要关联一个无参的方法,所以 lambda 表达式用一个内联的@( )
来设置点击的TabPage
为ActivatePage
。
- 按钮的文字通过
TabPage
的Text
属性设置。
下面的代码添加到TabControl
的代码区域。
string GetButtonClass(TabPage page)
{
return page == ActivePage ? "btn-primary" : "btn-secondary";
}
void ActivatePage(TabPage page)
{
ActivePage = page;
}
使用TabControl
添加一个TabControlTest
组件:
文件名:./Pages/TabControlTest.razor
@page "/tabcontroltest"
<TabControl>
<TabPage Text="Tab 1">
<h1>The first tab</h1>
</TabPage>
<TabPage Text="Tab 2">
<h1>The second tab</h1>
</TabPage>
<TabPage Text="Tab 3">
<h1>The third tab</h1>
</TabPage>
</TabControl>
@code { }
在./Shared/NavMenu 中添加TabControlTest
路由
省略部分代码
<div class="nav-item px-3">
<NavLink class="nav-link" href="tabcontroltest">
<span class="oi oi-plus" aria-hidden="true"></span> TabControl Test
</NavLink>
</div>
省略部分代码
这样就完了吗?我们看看现在的效果:
不对吧,三个TabPage
的内容全部显示出来了,解决这个问题只需要在TabPage
渲染ChildContent
时判断当前TabPage
是否为TabControl
选中的页,选中项才进行渲染:
@if (Parent.ActivePage == this)
{
@ChildContent
}
OK 代码完,效果见本文开头。
文中代码已放:Github