Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 模板Blazor组件_C#_Templates_Components_Blazor - Fatal编程技术网

C# 模板Blazor组件

C# 模板Blazor组件,c#,templates,components,blazor,C#,Templates,Components,Blazor,只是想用一个模板化的blazor组件来做一个CRUD风格的单页应用程序,它可以传递一个特定的对象,这样我就不必反复编写相同的样板代码了 例如,可以使用RenderFragment对象对以下部分进行模板化: @typeparam TItem <div> @if (AddObjectTemplate != null) { @AddObjectTemplate } else { <div style="floa

只是想用一个模板化的blazor组件来做一个CRUD风格的单页应用程序,它可以传递一个特定的对象,这样我就不必反复编写相同的样板代码了

例如,可以使用RenderFragment对象对以下部分进行模板化:

@typeparam TItem

<div>
    @if (AddObjectTemplate != null)
    {
        @AddObjectTemplate
    }
    else
    {
        <div style="float:left">
            <button class="btn btn-primary" @onclick="AddObject">Add Object</button>
        </div>
    }
</div>

@code {
    [Parameter]
    public RenderFragment AddObjectTemplate { get; set; }

    [Parameter]
    public IList<TItem> Items { get; set; }

}
@typeparam-TItem
@if(AddObjectTemplate!=null)
{
@AddObjectTemplate
}
其他的
{
添加对象
}
@代码{
[参数]
公共RenderFragment AddObjectTemplate{get;set;}
[参数]
公共IList项{get;set;}
}
然而,再往下看,我可能想要这样的东西:

<button class="btn btn-default" @onclick="@(() => EditObject(item.Id))">Edit</button>

protected void EditObject(int id)
{
    TItem cust = _itemServices.Details(id);
}
编辑
受保护的void EditObject(int id)
{
TItem cust=_itemServices.Details(id);
}
问题是,上面对EditObject(item.Id)的调用此时无法解析为特定对象,因为它不知道什么是TItem。是否有一种方法可以在模板组件中使用每个对象都必须实现的特定接口,或者有其他方法可以做到这一点


我们的想法是让AddObject、EditObject、DeleteObject等基本上做相同的事情,但对象类型不同。

因为您有
IList
作为参数,所以列表存在于该组件之外的组件结构的另一个级别。因此,最好使用添加、编辑和删除方法的
EventCallBack
属性,并在连接组件时设置实际方法。这将使模板组件仅成为渲染对象,并使要完成的实际“工作”接近需要完成工作的实际列表

当您设置模板组件时,您可能会尝试类似这样的方法,我在这方面取得了很好的效果

模板刀

@typeparam-TItem
模板
@foreach(项目中的var项目)
{
@项目模板(项目)
编辑项
}
@代码{
[参数]
公共IList项{get;set;}
[参数]
public EventCallback EditItemCallBack{get;set;}
[参数]
公共呈现片段项模板
}
容器剃须刀

容器
@客户名称
@代码{
公共列表客户{get;set;}
无效编辑客户(客户)
{
var customerId=customer.Id;
//在此处执行一些操作以更新客户
}
}
Customer.cs

公共类客户
{
公共int Id{get;set;}
公共字符串名称{get;set;}
}
这里的要点如下:

  • 实际的根列表和处理该列表的方法都位于模板化组件之外,因此上述所有内容都处于相同的抽象级别和相同的代码块

  • 模板组件接收一个列表、一个指定列表项类型的类型,以及一个对每个项执行的方法回调。(或一系列方法,您可以使用相同的方法添加您认为合适的“添加”和“删除”方法)。它还接收在Container.razor文件中调用代码时指定的
    呈现片段

  • 模板项中的“foreach”确保为每个TItem设置自己的RenderFragment、一组按钮和回调函数

  • 使用
    EventCallBack
    作为参数意味着您为其分配了一个方法,该方法期望返回整个TItem对象这很好,因为模板现在不关心TItem是什么类型,只关心它能够调用以TItem作为参数的方法处理TItem的实例现在是调用代码的责任,您不必试图约束泛型类型TItem。(我在Blazor中还没有做过这样的事情,可能是将来的版本)

  • 至于如何呈现您输入到其中的任何滴度,文档中对此进行了很好的解释


    希望这有帮助

    谢谢你的信息。我一直在做一些非常类似的事情,除了我想知道的不是让模板的客户端定义这些CRUD操作,而是它们是否可以是泛型的,因为我希望这些CRUD操作与它们使用的对象不同,例如创建一个TItem类型的对象,使用其ID字段作为键更新一个TItem类型的对象。通过使这些模型对象符合接口,我认为可以将通用CRUD操作定义为默认值,然后在需要更大灵活性的情况下定义回调函数。您可能需要使用反射来提取类型,然后基于类型运行开关块,或者使用模式匹配。对于每种类型,必须在开关表达式中有自己的方法。在本例中,我设置了一个注入服务,并将对象传递给服务上的方法,让该服务处理开关表达式、类型提取和CRUD操作。这样,您只需在一个位置维护开关代码和相关函数调用。