c# - Blazor 组件的模板页面
问题描述
基本上我正在尝试创建模板化组件和布局的混合。我想要一个可以重用的页面布局,并且仍然可以传递所需的参数。我认为这样做的一种方法可能是利用抽象基类。
如果我想通过渲染树构建来完成这一切,这可以通过我的第三个选项来解决,但我不想这样做。我可以接受由渲染树构建的基础(即选项 3),但不是从它继承的组件(即MyGrid.razor
)
我想做的事:
MyGrid.razor
@page "/mygrid"
@inherits GridPage @*or "layout" or whatever works*@
<Grid>
<Column>
<Column>
</Grid>
@code {
protected overrides string Title => "My Grid"
}
GridPage.cs
<header>@Title</header>
<div>@ChildContent</div>
@code {
[Parameter] public string Title { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
}
我尝试过的解决方案
- 布局
GridLayout
<header>@Title</header>
<div>@Body</div>
@code {
[CascadingParameter]
[Parameter] public string Title { get; set; }
}
问题是你必须记住这个参数是可用的,不需要隐含
- 模板
<GridPageTemplate Title="My Title">
<Grid>
<Column>
<Column>
</Grid>
</GridPageTemplate>
这里的问题是我必须用模板包装我的组件(没什么大不了的,但宁愿继承),我仍然不知道需要哪些参数来实现。
- 抽象基类
public abstract class GridPage : ComponentBase
{
protected abstract string Title { get; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenRegion(0);
builder.OpenElement(1, "header");
builder.AddContent(2, Title);
builder.CloseElement();
builder.CloseRegion();
builder.OpenElement(3, "div")
builder.OpenRegion(10);
this.BuildRenderTree(builder);
builder.CloseRegion();
builder.Closelement()
}
}
问题是这个似乎不起作用。我实际上认为这会导致它只接受组件并继续基本渲染(this.BuildRenderTree(builder);
)。
期望的结果
假设你有两个网格......一个Students
网格和一个网Classes
格。我希望它们每个都有不同的网格(和标题)。我想基本上为每个自定义标题和列。它们会有一个共同的布局标记(我称之为GridPage
),但MyGrid
(要么 要么Students
)Classes
会有所不同。
Students.razor
@page "/students"
@inherits GridPage
<Grid RowType=Student>
<Column For="StudentName">
<Column For="StudentAge">
<Column For="StudentHomeRoom">
</Grid>
@code {
protected overrides string Title => "Students"
}
Classes.razor
@page "/classes"
@inherits GridPage
<Grid RowType=Class>
<Column For="ClassName">
<Column For="ClassTime">
</Grid>
@code {
protected overrides string Title => "Classes"
}
他们都会输出
<header>Title_here</header>
<div>Grid_markup_here</div>
解决方案
创建具有逻辑所需的公共属性的抽象基类,然后将其扩展至您实际必须呈现的位置。
AbstractBaseClass.razor.cs
public class AbstractBaseClass<T> : ComponentBase
{
[Parameter]
public string Title {get;set;}
[Parameter]
public T TypedObject {get;set;}
[Parameter]
public RenderFragment<T> TypedComponent {get;set;}
[Parameter]
public RenderFragment CommonUi {get;set;}
}
在一种实现中:
IntType.razor
@inherits AbstractBaseClass<int>
@CommonUi
// or any other markup logic if any
@TypedComponent(TypedObject)
字符串类型.razor
@inherits AbstractBaseClass<string>
@CommonUi
// or any other markup logic if any
@TypedComponent(TypedObject)
然后将其与硬实现一起使用
<StringType TypedObject="StackOverflow" >
<CommonUi> /* Component common to both*/ </CommonUi>
</StringType>
<IntType TypedObject="2" >
<CommonUi> /* Component common to both*/ </CommonUi>
</IntType>
更新:如果你想完全避开模板部分,很简单:
CommonLayout.razor
<div>
<header>@Title</header>
@ChildContent
</div>
@code
{
[Parameter]
public string Title {get;set;}
[Parameter]
public RenderFragment ChildContent {get;set;}
}
学生剃须刀
<CommonLayout Title="Student Title">
<Grid RowType=Student>
<Column For="StudentName">
<Column For="StudentAge">
<Column For="StudentHomeRoom">
</Grid>
</CommonLayout>
ClassRender.razor
<CommonLayout Title="Class Title">
<Grid RowType=Class>
<Column For="ClassName">
<Column For="ClassTime">
</Grid>
</CommonLayout>
推荐阅读
- python - 有人对 ElasticMock python 模块有经验吗?
- c++ - 具有前向声明的不完整类型的 unique_ptr 将无法编译
- date - 减去两个日期和时间,看看后面的值是否超过 2 小时
- c# - 在 C# 中连接到多个 RabbitMQ 主机
- sql - 如果子查询不属于“分组依据”,则不支持“选择”或“排序依据”中的子查询
- python - 在 MacOS 中刷新 Excel 文件的外部数据
- javascript - 如何在javascript数据库中存储复杂对象?[JSON.stringify() 导致错误]
- reactjs - 覆盖 React 组件中的内部元素属性
- matlab - Running a for loop through 5 data structs
- c# - C# Setting a value in a single element of a multi-level array is setting the value in every element