Blazor创建TabControl组件
| Blazor University | 我要编辑、留言

不是全文翻译,部分翻译自认为可能不准确,就原文照搬了。

创建一个 Blazor TabControl 组件,有两个目标知识点:

  1. Pass data into a RenderFragment to give it context.
  2. Use a CascadingParameter to pass the parent TabControl component into its child TabPage components.

下面看最终效果图:

实操开始:

请先创建一个 Blazor 项目(Blazor Client 或者 Server 皆可,我们以 Blazor Server 为例),

第一步,创建两个组件:TabControlTabPageTabPage组件有一个父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

TabPageOnInitialized方法中添加下面这一行代码,使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会创建一个有以下特征的按钮:

  1. CSS 类设置为"btn",并通过GetButtonClass方法追加 CSS 类名,如果当前TabPageActivePage,添加 CSS 类btn-primary,否则添加btn-secondary
  2. 当点击按钮时会激活点击的TabPage

注意@onclick需要关联一个无参的方法,所以 lambda 表达式用一个内联的@( )来设置点击的TabPageActivatePage

  1. 按钮的文字通过TabPageText属性设置。

下面的代码添加到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

网站统计
网站创建
5年
文章分类
7个
文章总计
471篇
文章原创
106篇(22.51%)