首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Blazor组件模板化

Blazor组件模板化
EN

Stack Overflow用户
提问于 2020-04-21 22:27:05
回答 1查看 425关注 0票数 1

我正在考虑想出一个模板化的blazor组件来做一个CRUD风格的单页应用程序,它可以传入一个特定的对象,这样我就不必一次又一次地编写相同的样板代码。

因此,例如,如下所示,可以使用RenderFragment对象将其部分模板化:

代码语言:javascript
复制
@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; }

}

无论如何,我可能想要这样的东西:

代码语言:javascript
复制
<button class="btn btn-default" @onclick="@(() => EditObject(item.Id))">Edit</button>

protected void EditObject(int id)
{
    TItem cust = _itemServices.Details(id);
}

问题是,上面对EditObject(item.Id)的调用目前无法解析到特定的对象,因为它不知道TItem是什么。有没有办法在模板组件中使用每个对象都必须实现的特定接口,或者是否有其他方法来实现?

这个想法是让AddObject,EditObject,DeleteObject等基本上都做同样的事情,但对象的类型不同。

EN

回答 1

Stack Overflow用户

发布于 2020-04-21 23:44:09

由于您将IList<TItem>作为参数,因此该列表存在于此组件之外的组件结构的另一个级别。因此,最好使用Add、Edit和Delete方法的EventCallBack<T>属性,并在连接组件时设置实际方法。这使得您的模板组件只是一个呈现对象,并且您将实际要完成的“工作”保持在需要完成工作的实际列表附近。

当你设置你的模板组件时,你可以尝试这样的东西,我用它已经取得了很好的效果。

Templator.razor

代码语言:javascript
复制
@typeparam TItem

<h3>Templator</h3>

@foreach (var item in Items)
{

    @ItemTemplate(item)

    <button @onclick="@(() => EditItemCallBack.InvokeAsync(item))">Edit Item</button>
}

@code {

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

    [Parameter]
    public EventCallback<TItem> EditItemCallBack { get; set; }

    [Parameter]
    public RenderFragment<TItem> ItemTemplate
}

Container.Razor

代码语言:javascript
复制
<h3>Container</h3>

<Templator TItem="Customer" Items="Customers" EditItemCallBack="@EditCustomer">

    <ItemTemplate Context="Cust">
        <div>@Cust.Name</div>
    </ItemTemplate>

</Templator>

@code {

    public List<Customer> Customers { get; set; }

    void EditCustomer(Customer customer)
    {
        var customerId = customer.Id;

        //Do something here to update the customer

    }

}

Customer.cs

代码语言:javascript
复制
public class Customer
{
    public int Id { get; set; }

    public string Name { get; set; }

}

这里的关键点如下:

  1. 实际的根列表位于模板化组件之外,处理该列表的方法也是如此,因此以上所有内容都处于相同的抽象级别和相同的代码块中。
  2. 模板组件接收一个列表,一个指定列表项类型的类型,以及一个在每个项上执行的方法回调。(或者一系列方法,您可以根据需要使用相同的方法添加" add“和"Delete”方法)。它还接收在调用Container.razor文件中的代码时指定的<ItemTemplate>呈现片段。模板项中的‘
  3. ’确保每个TItem都为它自己的RenderFragment、一组按钮和回调EventCallBack<TItem>设置为参数,这意味着你给它分配了一个方法,该方法需要返回TItem的整个对象。这很好,因为模板现在不关心TItem是什么类型,只有它能够调用以TItem为参数的方法!处理任何TItem的实例现在都是调用代码的责任,并且您不必尝试约束泛型类型TItem。(我还没有在Blazor中做过任何幸运的事情,也许是将来的版本)

至于如何呈现您提供给它的任何TItem,文档HERE中对此进行了很好的解释。

希望这能有所帮助!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61345961

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档