一、创建 .NET 8.0 的 Blazor Web App 项目,并引用 BootstrapBlazor
二、在 Components 文件夹中创建 BBLayout 文件夹,并在此文件夹中保存 布局组件 Layout 的 7 个相关文件
![](https://i-blog.csdnimg.cn/direct/1504ff5fda984745bb5810f1201a5161.png)
图2-1:BBLayout 文件夹及 7 个相关文件
1. 菜单文件 BBLayoutMenu.cs:将菜单操作独立出来,方便后期更换菜单
using BootstrapBlazor.Components;
using Microsoft.AspNetCore.Components.Routing;
namespace BlazorWebAppWithBB.Components.BBLayout;
/// <summary>
/// 定义生成菜单的静态方法
/// </summary>
public class BBLayoutMenu
{
/// <summary>
/// 菜单全部折叠、展开
/// </summary>
/// <param name="menus"></param>
/// <param name="ExpandAll"></param>
private static void ExpandAllFun(List<MenuItem> menus, int ExpandAll)
{
if (ExpandAll == 1)
{
menus.ForEach(m => m.IsCollapsed = true);
}
if (ExpandAll == 2)
{
menus.ForEach(m => m.IsCollapsed = false);
}
}
/// <summary>
/// 获取测试菜单01
/// </summary>
/// <returns></returns>
public static IEnumerable<MenuItem> GetIconSideMenuItemsTest01(int ExpandAll)
{
return new List<MenuItem>
{
new () { Text = "Home", Icon = "fa-fw fa-solid fa-house", Url = "/" },
new () { Text = "counter", Icon = "fa-fw fa-solid fa-desktop", Url = "/counter" },
new () { Text = "weather", Icon = "fa-fw fa-solid fa-laptop", Url = "/weather" }
};
}
/// <summary>
/// 获取测试菜单02
/// </summary>
/// <returns></returns>
public static IEnumerable<MenuItem> GetIconSideMenuItemsTest02(int ExpandAll)
{
var menus = new List<MenuItem>
{
new MenuItem() { Text = "Index", Icon = "fa-solid fa-fw fa-home", Url = "/" , Match = NavLinkMatch.All},
new MenuItem("模板自带",icon:"fa-solid fa-fw fa-table")
{
Items=new List<MenuItem>
{
new("counter","/counter","fa-solid fa-fw fa-check-square"),
new("weather","/weather","fa-solid fa-fw fa-database"),
}
},
new MenuItem("一级菜单01",icon:"fa-solid fa-fw fa-flag")
{
Match = NavLinkMatch.All,
Items=new List<MenuItem>
{
new("二级菜单0101","/yj01/yj01ej01","fa-solid fa-fw fa-check-square")
{
Match=NavLinkMatch.All
},
new("二级菜单0102","/yj01/yj01ej02","fa-solid fa-fw fa-database"),
new("二级菜单0103","/yj01/yj01ej03","fa-solid fa-fw fa-database"),
}
},
new MenuItem("一级菜单02",icon:"fa-solid fa-fw fa-table")
{
Items=new List<MenuItem>
{
new("二级菜单0201","/yj02/yj02ej01","fa-solid fa-fw fa-check-square"),
new("二级菜单0202","/yj02/yj02ej02","fa-solid fa-fw fa-database"),
new("二级菜单0203","/yj02/yj02ej04","fa-solid fa-fw fa-database"),
}
},
new MenuItem("一级菜单03", icon: "fas fa-dog")
{
Items=new List<MenuItem>
{
new("二级菜单0301","/yj03/yj03ej01","fa-solid fa-fw fa-check-square"),
new("二级菜单0302","/yj03/yj03ej02","fa-solid fa-fw fa-database"),
new("二级菜单0303",icon: "fa-solid fa-fw fa-database")
{
Items=new List<MenuItem>
{
new("三级菜单030301" ,"/yj03/yj03ej03/yj03ej03sj01","fa-solid fa-fw fa-database"),
new("三级菜单030302" ,"/yj03/yj03ej03/yj03ej03sj02","fa-solid fa-fw fa-database"),
new("三级菜单030303" ,"/yj03/yj03ej03/yj03ej03sj03","fa-solid fa-fw fa-database"),
}
}
}
},
new MenuItem("操作日志", "/czrz/rz01",icon: "fa-solid fa-fw fa-heart fa-beat"),
};
ExpandAllFun(menus, ExpandAll);
return menus;
}
}
代码2-1:菜单文件
2. 参数类 BBLayoutParameters.cs:将 Layout 的参数对象化,方便后期使用
namespace BlazorWebAppWithBB.Components.BBLayout;
public class BBLayoutParameters
{
//打开抽屉
public bool IsOpen { get; set; }
//使用多标签
public bool UseTabSet { get; set; } = true;
//主题配色 名称
public string Theme { get; set; } = "";
//固定调整(不随滚动条滚动):固定页头、固定页脚、固定标签
public bool IsFixedHeader { get; set; } = true;
public bool IsFixedFooter { get; set; } = true;
public bool IsFixedTab { get; set; }
//布局调整:上下结构、左右结构(侧边栏是否占满整个左边)
public bool IsFullSide { get; set; } = true;
//显示页脚
public bool ShowFooter { get; set; } = true;
//显示返回顶端按钮(在页脚中)
public bool ShowGotoTop { get; set; } = true;
//显示收缩展开 Bar(收缩按钮)
public bool ShowCollapseBar { get; set; } = true;
//手风琴菜单
public bool IsAccordion { get; set; } = true;
//菜单全部折叠、展开
public int ExpandAll { get; set; } = 0;
}
代码2-2:参数类文件
3. 抽屉组件 BBLayoutDrawer.razor(专用样式文件 BBLayoutDrawer.razor.css):将 Drawer 组件独立出来,方便后期使用
<Drawer Placement="Placement.Right" @bind-IsOpen="@LayoutParameters.IsOpen" IsBackdrop="true">
<div class="layout-drawer-body">
<div class="btn btn-info w-100" @onclick="@(e => LayoutParameters.IsOpen = false)">点击关闭</div>
<GroupBox Title="布局调整">
<div class="row">
<div class="col-6">
<div class="layout-item @(LayoutParameters.IsFullSide ? "active d-flex" : "d-flex")" @onclick="@(async e =>{ LayoutParameters.IsFullSide = true;await UpdateParameters();})" data-toggle="tooltip" title="左右结构">
<div class="layout-left d-flex flex-column">
<div class="layout-left-header"></div>
<div class="layout-left-body flex-fill"></div>
</div>
<div class="layout-right d-flex flex-column flex-fill">
<div class="layout-right-header"></div>
<div class="layout-right-body flex-fill"></div>
<div class="layout-right-footer"></div>
</div>
</div>
</div>
<div class="col-6">
<div class="layout-item flex-column @(LayoutParameters.IsFullSide ? "d-flex" : "active d-flex")" @onclick="@(async e =>{ LayoutParameters.IsFullSide = false;await UpdateParameters();})" data-toggle="tooltip" title="上下结构">
<div class="layout-top">
</div>
<div class="layout-body d-flex flex-fill">
<div class="layout-left">
</div>
<div class="layout-right flex-fill">
</div>
</div>
<div class="layout-right-footer">
</div>
</div>
</div>
</div>
</GroupBox>
<GroupBox Title="固定调整">
<div class="row">
<div class="col-6 d-flex align-items-center">
<Switch IsDisabled="@(LayoutParameters.IsFixedTab)" @bind-Value="@LayoutParameters.IsFixedHeader" @bind-Value:after="UpdateParameters" OnColor="@Color.Success" OffColor="@Color.Secondary" title="@fixTitle"></Switch>
</div>
<div class="col-6 text-right">
<span class="cell-label">固定页头</span>
</div>
</div>
<div class="row mt-3">
<div class="col-6 d-flex align-items-center">
<Switch IsDisabled="@(!LayoutParameters.ShowFooter || LayoutParameters.IsFixedTab)" @bind-Value="@LayoutParameters.IsFixedFooter" @bind-Value:after="UpdateParameters" OnColor="@Color.Success" OffColor="@Color.Secondary" title="@fixTitle"></Switch>
</div>
<div class="col-6 text-right">
<span class="cell-label">固定页脚</span>
</div>
</div>
<div class="row mt-3">
<div class="col-6 d-flex align-items-center">
<Switch @bind-Value="@LayoutParameters.IsFixedTab" @bind-Value:after="UpdateParameters" OnColor="@Color.Success" OffColor="@Color.Primary"></Switch>
</div>
<div class="col-6 text-right">
<span class="cell-label">固定标签</span>
</div>
</div>
</GroupBox>
<GroupBox Title="显示设置">
<div class="row">
<div class="col-6 d-flex align-items-center">
<Switch IsDisabled="@(LayoutParameters.IsFixedTab)" @bind-Value="@LayoutParameters.ShowFooter" @bind-Value:after="UpdateParameters" OnColor="@Color.Success" OffColor="@Color.Secondary" title=""></Switch>
</div>
<div class="col-6 text-right">
<span class="cell-label">页脚</span>
</div>
</div>
<div class="row mt-3">
<div class="col-6 d-flex align-items-center">
<Switch IsDisabled="@(!LayoutParameters.ShowFooter)" @bind-Value="@LayoutParameters.ShowGotoTop" @bind-Value:after="UpdateParameters" OnColor="@Color.Success" OffColor="@Color.Secondary" title="该按钮默认位于在页脚中右侧"></Switch>
</div>
<div class="col-6 text-right">
<span class="cell-label">返回顶端按钮</span>
</div>
</div>
<div class="row mt-3">
<div class="col-6 d-flex align-items-center">
<Switch @bind-Value="@LayoutParameters.ShowCollapseBar" @bind-Value:after="UpdateParameters" OnColor="@Color.Success" OffColor="@Color.Primary"></Switch>
</div>
<div class="col-6 text-right">
<span class="cell-label">收缩按钮</span>
</div>
</div>
</GroupBox>
<GroupBox Title="主题配色">
<div class="row">
@for (int i = 0; i <= 5; i++)
{
var current = i;
<div class="col-2">
<span class="color color@(i)"
@onclick="@(async e => {LayoutParameters.Theme = $"color{current}";await UpdateParameters();})">
</span>
</div>
}
</div>
</GroupBox>
<GroupBox Title="菜单设置">
<div class="row">
<div class="col-6 d-flex align-items-center">
<Switch @bind-Value="@LayoutParameters.IsAccordion" @bind-Value:after="UpdateParameters" OnColor="@Color.Success" OffColor="@Color.Primary"></Switch>
</div>
<div class="col-6 d-flex align-items-center justify-content-end">
<span class="cell-label bg-lightXXX">手风琴效果</span>
</div>
</div>
<div class="row mt-3 d-flex justify-content-around">
<Button IsDisabled="@(LayoutParameters.IsAccordion)" class="col-3" Size="Size.ExtraSmall" ButtonStyle="ButtonStyle.Round" Color="Color.Primary" OnClick="All02">全部展开</Button>
<Button IsDisabled="@(LayoutParameters.IsAccordion)" class="col-3" Size="Size.ExtraSmall" ButtonStyle="ButtonStyle.Round" Color="Color.Primary" OnClick="All01">全部折叠</Button>
</div>
</GroupBox>
<GroupBox Title="更多设置">
<div class="row">
<div class="col-6 d-flex align-items-center">
<Switch @bind-Value="@LayoutParameters.UseTabSet" @bind-Value:after="UpdateParameters" OnColor="@Color.Success" OffColor="@Color.Primary"></Switch>
</div>
<div class="col-6 text-right">
<span class="cell-label">@(LayoutParameters.UseTabSet ? "多标签" : "单页")</span>
</div>
</div>
</GroupBox>
</div>
</Drawer>
@code {
string fixTitle = "固定标签时,默认固定页头、页脚";
// 定义当前组件的“组件参数”,用于在父组件中使用 @bind-{PROPERTY} 将父组件中的“变量”绑定到本组件参数。
// 使用 = new() 初始化,否则报 warning CS8618 非空警告。
[Parameter]
public BBLayoutParameters LayoutParameters { get; set; } = new();
// 必须的:与“组件参数”配合使用,定义组件参数绑定事件,用于回传参数到父组件。
// 事件命名语法:{PARAMETER NAME}Changed
[Parameter]
public EventCallback<BBLayoutParameters> LayoutParametersChanged { get; set; }
// 响应组件中的事件,同时回传参数到父组件。
private async Task UpdateParameters()
{
// 此处可以有当前组件的操作代码。
// ......
// 回传
// System.Console.WriteLine(LayoutParameters.Theme);
// 固定标签 时,必须固定 页头、页脚、显示页脚;
// 不 显示页脚 时,固定页脚 选项不可用【<Switch IsDisabled="@(!LayoutParameters.ShowFooter)" 】;
if (LayoutParameters.IsFixedTab)
{
LayoutParameters.IsFixedFooter = true;
LayoutParameters.IsFixedHeader = true;
LayoutParameters.ShowFooter = true;
}
// 目前,固定标签 时,返回顶端 无效:因为返回目标为 标签、此时顶端=标签??可能后面会修复 ??
if (LayoutParameters.IsFixedTab)
{
LayoutParameters.ShowGotoTop = false;
}
if (LayoutParameters.IsAccordion)
{
LayoutParameters.ExpandAll = 0;
}
await LayoutParametersChanged.InvokeAsync(LayoutParameters);
}
// 全部展开、折叠
private async void All01()
{
LayoutParameters.ExpandAll = 1;
await UpdateParameters();
}
private async void All02()
{
LayoutParameters.ExpandAll = 2;
await UpdateParameters();
}
}
代码2-3:BBLayoutDrawer.razor 组件完整代码
.layout-drawer-body {
padding: 1rem;
}
.layout-drawer-body ::deep .groupbox {
margin-top: 1rem;
}
.layout-drawer-body ::deep .btn-info {
margin-bottom: 1rem;
}
.cell-label {
line-height: 35px;
}
.layout-item {
/*--bb-layout-sidebar-bg: #f8f9fa;
--bb-layout-footer-bg: #e9ecef;*/
cursor: pointer;
border: 2px solid #e9ecef;
padding: 4px;
border-radius: 4px;
height: 80px;
width: 120px;
transition: border .3s linear;
}
.layout-item:hover,
.layout-item.active {
border: 2px solid #28a745;
}
.layout-item .layout-left {
width: 30%;
/*border-right: 1px solid var(--bs-border-color);*/
}
.layout-item .layout-left .layout-left-header {
height: 16px;
/*background-color: var(--bb-header-bg);*/
background-color: #367fa9;
}
.layout-item .layout-left .layout-left-body,
.layout-item .layout-body .layout-left {
/*background-color: var(--bb-layout-sidebar-bg);*/
background-color: #2f4050;
}
.layout-item .layout-right .layout-right-header,
.layout-item .layout-top {
/*background-color: var(--bb-header-bg);*/
background-color: #17a2b8;
height: 16px;
}
.layout-item .layout-right .layout-right-footer,
.layout-item .layout-right-footer {
/*background-color: var(--bb-layout-footer-bg);*/
background-color: #5b6e84;
height: 12px;
}
.layout-item .layout-top,
.layout-item .layout-body,
.layout-item .layout-right-footer {
width: 100%;
}
/*原模板使用了 text-right 样式,但不存在,自己补写一个*/
.text-right {
text-align: right;
}
代码2-4: BBLayoutDrawer.razor 组件专用样式文件
4. 布局文件 BBLayout.razor(专用样式文件 BBLayout.razor.css):作用等同于 MainLayout.razor,实现一个项目多种布局
@* 【BBLayout 使用方法】
1.共涉及 7 个文件:
BBLayout.razor 本组件
BBLayout.razor.css
BBLayoutDrawer.razor 抽屉组件
BBLayoutDrawer.razor.css
BBLayoutMenu.cs 获取菜单静态方法
BBLayoutParameters.cs 参数类
BBLayout.css 修改默认样式值
2.在 Layout 组件中
(1)定义参数对象
private BBLayoutParameters layoutParameters = new BBLayoutParameters();
(2)右侧抽屉,初始不显示
<BBLayoutDrawer @bind-LayoutParameters="layoutParameters" />
(3)单击显示右侧抽屉
<div class="layout-drawer" @onclick="@(e => layoutParameters.IsOpen = !layoutParameters.IsOpen)"><i class="fa fa-gears"></i></div>
3.在 App.razor 中
<link rel="stylesheet" href="BBLayout.css" />
问题1:固定标签 时,返回顶端 无效 ??
注1:使用“多标签”时,全部标签关闭,默认显示 TabDefaultUrl 的标签;
此时要求,TabDefaultUrl 要明确指定 Text、Icon 属性,否则标签的文本、图标会显示错误。
TabDefaultUrl 的属性指定示例代码如下所示。
@attribute [TabItemOption(Text = "Home", Icon = "fa-fw fa-solid fa-house")]
问题2:增加 以下两个参数的设置 ???
SideWidth="0" IsPage="true"
*@
@inherits LayoutComponentBase
<BootstrapBlazorRoot>
<Layout SideWidth="0" IsPage="true" AdditionalAssemblies="new[] { GetType().Assembly }"
UseTabSet="@layoutParameters.UseTabSet"
IsFixedHeader="@layoutParameters.IsFixedHeader"
IsFixedFooter="@layoutParameters.IsFixedFooter"
IsFullSide="@layoutParameters.IsFullSide"
ShowFooter="@layoutParameters.ShowFooter"
ShowGotoTop="@layoutParameters.ShowGotoTop"
ShowCollapseBar="@layoutParameters.ShowCollapseBar"
IsAccordion="@layoutParameters.IsAccordion"
class="@LayoutClassString"
Menus="@(BBLayoutMenu.GetIconSideMenuItemsTest01(layoutParameters.ExpandAll))"
TabDefaultUrl="/">
<Header>
<span class="ms-3 flex-sm-fill d-none d-md-block">Blazor Web App 模板引用 BootstrapBlazor</span>
<div class="ms-2 flex-fill d-md-none">项目简称</div>
<span class="mx-3 d-none d-lg-block">实时提示信息</span>
<span class="mx-3 d-none d-sm-block">登录用户名</span>
<span class="mx-3 d-none d-lg-block">
<Logout ImageUrl="favicon.png" DisplayName="超级管理员" UserName="Admin">
<LinkTemplate>
<a href="#"><i class="fa-solid fa-suitcase"></i>个人中心</a>
<a href="#"><i class="fa-solid fa-cog"></i>设置</a>
<a href="#"><i class="fa-solid fa-bell"></i>通知<span class="badge badge-pill badge-success"></span></a>
<LogoutLink />
</LinkTemplate>
</Logout>
</span>
@* 单击显示右侧抽屉 *@
<div class="layout-drawer" @onclick="@(e => layoutParameters.IsOpen = !layoutParameters.IsOpen)"><i class="fa fa-gears"></i></div>
</Header>
<Side>
<div class="layout-banner">
<img alt="logo" class="layout-logo" src="favicon.png" />
<div class="layout-title">
<span>项目名称</span>
</div>
</div>
</Side>
<Main>
<CascadingValue Value="this" IsFixed="true">
@Body
</CascadingValue>
</Main>
<Footer>
<div class="text-center flex-fill">
<a class="layout-footer-gray" target="_blank" href="">版权说明、使用说明</a>
</div>
</Footer>
@* Blazor Web App 模式中弃用
<NotFound>
<p>Sorry, there's nothing at this address.</p>
</NotFound> *@
</Layout>
@* 右侧抽屉,初始不显示 *@
<BBLayoutDrawer @bind-LayoutParameters="layoutParameters" />
</BootstrapBlazorRoot>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
@code {
// 定义参数对象
private BBLayoutParameters layoutParameters = new BBLayoutParameters();
// 设置 IsFixedTab
private string? LayoutClassString => CssBuilder.Default()
.AddClass(layoutParameters.Theme)
.AddClass("is-fixed-tab", layoutParameters.IsFixedTab)
.Build();
/* 获取菜单
方法2:新方法,直接使用静态方法获取,使得菜单独立出去,示例如下。
Menus="@(BBLayoutMenu.GetIconSideMenuItemsTest01(layoutParameters.ExpandAll))"
方法1:定义 Menus,使用示例:<Layout Menus="Menus"></Layout>
private IEnumerable<MenuItem>? Menus { get; set; }
// 初始化时读取 菜单
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
Menus = BBLayoutMenu.GetIconSideMenuItemsTest01(layoutParameters.ExpandAll);
}
*/
}
代码2-5:布局组件 Layout 完整代码
.layout-drawer {
padding: 13px;
margin-right: -1rem;
cursor: pointer;
}
.layout-drawer:hover {
background-color: #1893a7;
}
.layout-banner {
border-bottom: 1px solid var(--bs-border-color);
}
.layout-banner .layout-logo {
border: 1px solid var(--bb-header-color);
}
/*设置footor颜色*/
.layout-footer-gray {
color: gray;
cursor: pointer;
}
.layout-footer-gray:hover {
color: dimgrey;
}
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
代码2-6:布局组件 Layout.raror 专用样式文件
5. 默认样式文件 BBLayout.css,此文件需要存放在文件夹 wwwroot 中
/* ********** 以下 css 是从 BootstrapBlazor 中提取、修改的,供 BBLayout.razor 使用。 ********** */
/* 注1:本文件(BBLayout.css)需要存放在 wwwroot 文件夹中,
并且在 App.razor 中使用 <link rel="stylesheet" href="BBLayout.css" /> 进行引用。
注2:<Layout> 组件中自带的默认样式(.layout、.layout-header、.layout-side、......),
只能在 本文件中 修改其值:在 BBLayout.razor.css 中进行修改,会因为 样式隔离 无效。*/
/*
:root {
--bb-header-color: #e0e0e0;
--bb-header-bg: #702cf8;
--bb-font-weight: 500;
--bb-title-color: #1f2f3d;
--bb-sub-font-size: 1.2rem;
}
.navbar {
--bs-navbar-color: rgba(255,255,255,.85);
--bs-navbar-hover-color: rgb(255,255,255);
}
.bb-sub {
margin-top: .25rem;
font-size: 86%;
color: #c0c4cc;
}
*/
@supports not selector(::-webkit-scrollbar) {
.scroll {
scrollbar-color: rgba(0,0,0,0.3) rgba(0,0,0,0);
scrollbar-width: thin;
}
}
.menu {
--bb-menu-active-color: #702cf8;
--bb-menu-bar-bg: #702cf8;
--bb-menu-item-hover-bg: #702cf8;
--bb-menu-item-hover-color: #fff;
}
.layout {
/* 包含 Side 上部
--bb-header-color: #e0e0e0;
--bb-header-bg: #702cf8;*/
--bb-layout-header-background: var(--bb-header-bg);
--bb-layout-sidebar-banner-background: var(--bb-header-bg);
--bb-layout-header-color: var(--bb-header-color);
--bb-layout-title-color: var(--bb-header-color);
/*以下 css 代码控制固定标签,IsFixedTab 使用*/
--bb-footer-height: 0px;
/*
--bb-layout-header-height: 50px;
--bb-layout-header-backgound: #17a2b8;
--bb-layout-headerbar-backgound: #1ab394;
--bb-layout-headerbar-border-color: #1ab394;
--bb-layout-footer-backgound: #5b6e84;
--bb-layout-footer-height: 40px;
*/
/* 隐藏 user 部分:MainLayout.razor 中 layout-user 的默认高度:不显示,此处设置为 0 ;
原值:65px,通过运行时按 F12 查看源码找到;
侧边栏删除了“用户名”块,设置高度为 0,以便其它css计算时使用;
--bb-layout-user-height: 0px;*/
/*
--bb-layout-sidebar-width: 214px;
--bb-layout-sidebar-collapse-width: 70px;
--bb-layout-sidebar-banner-background: #367fa9;
--bb-layout-sidebar-scrollbar-background: #c1c1c1;
--bb-layout-sidebar-backgound: #343a40;
--bb-layout-sidebar-color: #c2c7d0;
--bb-layout-title-color: #e9ecef;
display: flex;
height: 100%;
width: 100%;
flex-direction: column
*/
}
.layout:not(.has-footer) {
--bb-layout-footer-height: 0px;
}
.layout.has-footer {
/*以下 css 代码控制固定标签,IsFixedTab 使用*/
--bb-footer-height: 40px;
}
.layout.is-page .layout-right {
background-color: #fff;
}
.layout-header {
border-bottom: 1px solid var(--bs-border-color);
}
.layout-side {
border-right: 1px solid var(--bs-border-color);
}
.layout-footer {
border-top: 1px solid var(--bs-border-color);
}
.dropdown-logout {
--bb-logout-text-color: var(--bb-header-color);
}
.logout-avatar {
border-radius: 50%;
}
.dropdown-user img {
border-radius: 50%;
}
.is-fixed-tab .tabs-body {
height: calc(100vh - var(--bb-layout-header-height) - var(--bb-tabs-item-height) - var(--bb-footer-height));
overflow: auto;
flex: initial;
}
.is-fixed-tab .tabs-body .tabs-body-content {
height: auto;
min-height: 100%;
}
/* ********** 以下 css 是从 BootstrapBlazor 中提取、修改的,供 BBLayoutDrawer.razor 中的 主题配色 使用。 ********** */
.color {
width: 1.5rem;
height: 1.5rem;
display: block;
cursor: pointer;
border: 2px solid #e9ecef;
border-radius: 4px;
transition: border .3s linear;
}
.color:hover {
border: 2px solid #28a745;
}
.color1,
.layout.is-page.color1 .layout-header {
background-color: #409eff;
}
.layout.is-page.color1 .layout-side .layout-banner {
background-color: #3e84d0
}
.layout.is-page.color1 .layout-side {
background-color: #212529;
color: #ebeef5;
}
.layout.is-page.color1 .layout-footer {
background-color: #343a40;
}
.layout.is-page.color1 .layout-header-bar {
background-color: #2b7cd0;
border-color: #014186;
}
.layout.is-page.color1 .layout-drawer:hover {
background-color: #3184dc;
}
.color2,
.layout.is-page.color2 .layout-header {
background-color: #28a745;
}
.layout.is-page.color2 .layout-side .layout-banner {
background-color: #24903d
}
.layout.is-page.color2 .layout-side {
background-color: #212529;
color: #ebeef5;
}
.layout.is-page.color2 .layout-footer {
background-color: #343a40;
}
.layout.is-page.color2 .layout-header-bar {
background-color: #258c3c;
border-color: #014186;
}
.layout.is-page.color2 .layout-drawer:hover {
background-color: #24903d;
}
.color3,
.layout.is-page.color3 .layout-header {
background-color: #e83e8c;
}
.layout.is-page.color3 .layout-side .layout-banner {
background-color: #c5417e
}
.layout.is-page.color3 .layout-side {
background-color: #212529;
color: #ebeef5;
}
.layout.is-page.color3 .layout-footer {
background-color: #343a40;
}
.layout.is-page.color3 .layout-header-bar {
background-color: #c73477;
border-color: #014186;
}
.layout.is-page.color3 .layout-drawer:hover {
background-color: #c5417e;
}
.color4,
.layout.is-page.color4 .layout-header {
background-color: #ffc107;
}
.layout.is-page.color4 .layout-side .layout-banner {
background-color: #e4af10
}
.layout.is-page.color4 .layout-side {
background-color: #212529;
color: #ebeef5;
}
.layout.is-page.color4 .layout-footer {
background-color: #343a40;
}
.layout.is-page.color4 .layout-header-bar {
background-color: #e2b221;
border-color: #014186;
}
.layout.is-page.color4 .layout-drawer:hover {
background-color: #e4af10;
}
.color5,
.layout.is-page.color5 .layout-header {
background-color: #17a2b8;
}
.color6,
.layout.is-page.color6 .layout-header {
background-color: #6610f2;
}
.layout.is-page.color6 .layout-side .layout-banner {
background-color: #4b0cb3
}
.layout.is-page.color6 .layout-side {
background-color: #212529;
color: #ebeef5;
}
.layout.is-page.color6 .layout-footer {
background-color: #343a40;
}
.layout.is-page.color6 .layout-header-bar {
background-color: #4b0ab5;
border-color: #014186;
}
.layout.is-page.color6 .layout-drawer:hover {
background-color: #4b0cb3;
}
代码2-7:修改布局组件 Layout.razor 需要的默认样式
6. 修改 App.razor 文件,引用 BBLayout.css 样式文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
@* BootstrapBlazor 中已集成 Bootstrap 最新版,项目模板自带的则不再需要。
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" /> *@
@* 引用 BootstrapBlazor 样式(已集成 Bootstrap 最新版)。 *@
<link rel="stylesheet" href="_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css" />
@* FontAwesoem 字体样式 注意需要使用 NuGet 引用 BootstrapBlazor.FontAwesome 包。 *@
<link rel="stylesheet" href="_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css" />
@* 如果不使用 Motronic 样式,则下句不需要。 *@
<link rel="stylesheet" href="_content/BootstrapBlazor/css/motronic.min.css" />
@* 自动生成的当前项目的样式表文件,可以保存自定义样式。 *@
<link rel="stylesheet" href="app.css" />
@* 自动生成的隔离样式文件,不需要修改。 *@
<link rel="stylesheet" href="BlazorWebAppWithBB.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" />
@* 创建 Blazor Web App 项目时选择的是 Server、Global 模式,则此处自动生成匹配说明:@rendermode="InteractiveServer"。 *@
<HeadOutlet @rendermode="InteractiveServer" />
@* 布局组件 Layout 使用的默认样式 *@
<link rel="stylesheet" href="BBLayout.css" />
</head>
<body>
@* 创建 Blazor Web App 项目时选择的是 Server、Global 模式,则此处自动生成匹配说明:@rendermode="InteractiveServer"。
注1:此处指定 rendermode 后,则在其它 razor 组件中可以不再单独添加。
注2:如果创建项目时选择 Server、Per page/component 模式,则需要在每个有动态更新操作的 razor 文件中单独指定 rendermode。 *@
<Routes @rendermode="InteractiveServer" />
@* BootstrapBlazor 引用 *@
<script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></script>
<script src="_framework/blazor.web.js"></script>
</body>
</html>
代码2-8:修改后的 App.razor 完整代码
三、使用 BBLayout 切换布局:在 Pages 文件夹中创建 _Imports.razor ,统一指定当前文件夹中 razor 文件使用的 Layout:原来 Componetns 文件夹中的 _Imports.razor 保存不变。
![](https://i-blog.csdnimg.cn/direct/3c9b95cbb7ba49518533dfa0b900ce46.png)
图3-1:Pages 文件夹专用的 _Imports.razor
@* 注:可以有多个 _Imports.razor,每个 _Imports.razor 对所在文件夹中的 razor 文件生效。*@
@* 统一指定当前文件夹中 razor 文件使用的 Layout。
注:优先级低于 razor 文件中的 Layout 指定语句。*@
@* @layout BlazorWebAppWithBB.Components.Layout.BBLayout *@
@layout BlazorWebAppWithBB.Components.BBLayout.BBLayout
代码3-1:使用 Pages 文件夹专用的 _Imports.razor 统一指定布局组件 Layout
@page "/"
@* 指定使用 BBLayout
@layout BlazorWebAppWithBB.Components.Layout.BBLayout*@
@* 显示指定标签属性:如果不显示指定,在 Layout 组件中选择“关闭所有标签”时,
默认打开 Home ,但是标签是关闭前的活动标签。*@
@attribute [TabItemOption(Text = "Home", Icon = "fa-fw fa-solid fa-house")]
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
代码3-2:修改后的 Home.razor 完整代码,不再需要单独指定 Layout
@page "/counter"
@* 指定使用 BBLayout
@layout BlazorWebAppWithBB.Components.Layout.BBLayout*@
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
代码3-3:修改后的 Counter.razor 完整代码,不再需要单独指定 Layout
四、运行程序,查看效果
![](https://i-blog.csdnimg.cn/direct/40b899ccdcbe4711878de2c63f15dc71.png)
图4-1:单击右上角按钮打开 设置 侧边栏