在 Blazor 组件中向泛型 RenderFragment 传递额外数据

4

我有一个简单的Blazor组件,它遍历一个通用列表:

@typeparam TItem;

 @foreach (var item in List)
        {
            @ElementTemplate(item); // What code should be here to pass i to the ElementTemplate????
            i++;
        }

@code {
    int i = 0;


    [Parameter] public List<TItem> List { get; set; }
    [Parameter] public RenderFragment<TItem> ElementTemplate { get; set; }
  }

我有另一个简单的组件,它将获取一个项目和索引来渲染数据(Employee):

<div> @Index . @Person.Name </div>

@code{
    [Parameter] public Person { get; set; }
    [Parameter] public int Index { get; set; }

}

在我的主页上,我有以下内容:

<GenericList List="employees">
    <ElementTemplate>
        <Employee Person="context" Index="?"></Employee>
    </ElementTemplate>
</GenericList>

您可以看到,Employee组件需要一个Index参数,我该如何从GenericList组件传递Index? 在这个例子中,变量“i”应该被传递到ElementTemplate以及Generic TItem对象本身。


你不能这样做 - 因为你明确地指定了 ElementTemplate 只能接收单个数据项。如果你想让它包含多个数据,你可以让它继承自一个基类或实现一个接口,并将其作为泛型约束使用。或者,将数据项设为 dynamic 类型,但这会失去泛型的好处。 - Panagiotis Kanavos
你可以设置一个字典来将你的模型类型映射到一个用于渲染的组件。使用它来传递列表。我扩展了ComponentBase以用于映射的组件,ViewComponentBase<TModel> : ComponentBase - Brian Parker
2个回答

8

我认为快速/简单的方法是使用元组作为RenderFragment上下文:

@foreach (var item in List)
{
  @ElementTemplate((item,i));
  i++;
}

@code {
  int i=0;
  [Parameter] public List<TItem> List { get; set; }
  [Parameter] public RenderFragment<(TItem item, int index)> ElementTemplate { get; set; }
}

然后您的标记变成:
<GenericList List="employees">
    <ElementTemplate>
        <Employee @key=@context.index Person=@context.item Index=@context.index></Employee>
    </ElementTemplate>
</GenericList>

如果您喜欢的话,可以在GenericList中使用一个实用类而不是一个元组。

我喜欢元组,但是@key=context或者至少@key=context.item会更好吗?索引与员工内容的耦合度最低。假设您删除了一个项目。 - H H
好吧,我不想深入讨论这些索引整数与数据实际上并没有可靠的耦合关系的问题,只是想偷偷地将 @key 放在那里——使用最快速的类型。但你可能是对的——这完全取决于实际的现实世界内容。 - Mister Magoo

3
你可以为你的上下文定义一个复杂的类。
在GenericList.razor中定义一个类:
public class ListContext
{
    public TItem Item {get; set;}
    public int Index {get; set;}
}

并将此类用作您模板的上下文类型:

[Parameter] 
public RenderFragment<ListContext> ElementTemplate { get; set; }

然后,当您调用这个模板时,您只需创建一个新类并设置正确的参数:

@foreach (var item in List)
{
    @ElementTemplate(new ListContext{Item = item, Index = i});
    i++;
}

这是一个工作示例:https://blazorrepl.com/repl/cuvakzPF21sXSZGK54

谢谢你,但这不是我想要做的方式。 - nAviD
你确切想要实现什么?或许使用Cascading value传递GenericList组件的索引会起作用? - Kristian.mariyanov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接