不是全文翻译,部分翻译自认为可能不准确,就原文照搬了。
创建一个Blazor TabControl组件,有两个目标知识点:
下面看最终效果图:
请先创建一个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组件:
文件路径:./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();
}
}
在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
会创建一个有以下特征的按钮:
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代码完,效果见本文开头。
原文作者:blazor university 原文链接:https://blazor-university.com/templating-components-with-renderfragements/creating-a-tabcontrol/ 文中代码已放:Github[1]
[1]Github: https://github.com/dotnet9/BlazorDemo