不是全文翻译,部分翻译自認為可能不準確,就原文照搬了。
建立一個 Blazor TabControl 元件,有兩個目標知識點:
- 將資料傳入 RenderFragment 中,賦予它上下文(context)。
- 使用 CascadingParameter 將父層 TabControl 元件傳遞給其子層 TabPage 元件。
下面看最終效果圖:

實作開始:
請先建立一個 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(); } }
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();
}
為 TabPage 元件加上一個 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