【问题标题】:How can I render a component in Blazor that is defined as object?如何在 Blazor 中呈现定义为对象的组件?
【发布时间】:2021-07-06 10:31:52
【问题描述】:

我有以下代码:

<div>
@if (Components != null && Components.Count != 0) {
   foreach (ComponentBase child in Components) {
      // Render the child component here
   }
}
</div>

如何使用 RenderFragment 渲染子对象?子对象是一个模板组件,它继承了其他类(上面有 ComponentBase)。

问题是子对象已经设置了所有参数,所以我不想使用对象数据再次设置所有 RenderFragment 参数。

我在 foreach 循环中尝试过但没有奏效的方法:

foreach (ComponentBase child in Components) {
  @child // <-- does render the class text
}

foreach (ComponentBase child in Components) {
  <ComponentBase>@child</ComponentBase> // <-- error
}

foreach (ComponentBase child in Components) {
  RenderFragment renderChild = (builder) => { builder.OpenComponent(0, child.GetType()); builder.CloseComponent(); };
@renderChild; // <-- I want to render the child object as this does nothing
}

【问题讨论】:

  • “问题是子对象已经设置了它的所有参数”——这听起来像是一个问题——Blazor 希望创建和初始化所有组件——并管理它们的参数。如果您实例化自己并填充参数,那么您正在破坏核心渲染系统。
  • 将此示例视为包含特定组件的容器。因此,我没有使用 及其参数,而是有一个 ,它可以在列表中包含多个 ButtonComponents。这是某些 css 定位和设置主容器的绝对样式所必需的。
  • 目前还不清楚你想要实现什么——而且你最后的评论并没有改变——你是通过代码创建组件的实例吗?
  • 是的。我想以某种方式动态呈现这些实例
  • 好的,不支持 - 您需要让 Blazor 创建组件的实例并跟踪参数。

标签: c# blazor


【解决方案1】:

这几乎是 .net6 中即将推出的 DynamicComponent 的等价物

您可以通过Type 传递类型或通过TypeString 传递类型名称

public class ComponentView : ComponentBase
{
    [Parameter]
    public Type Type { get; set; }

    [Parameter]
    public string TypeString { get; set; }

    private Dictionary<string, object> parameters;

    [Parameter]
    public Dictionary<string, string> Values { get; set; }

    protected override void OnParametersSet()
    {
        if (Values is null) {
            parameters = null;
        }
        else {
            parameters = new Dictionary<string, object>();
            foreach (var pair in Values) {
                parameters[pair.Key] = pair.Value;
            }
        }
        base.OnParametersSet();
    }



    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        if (Type is null) {
            if (string.IsNullOrWhiteSpace(TypeString)) {
                throw new Exception("You must use either Type or the TypeString paramater");
            }
            Type = Type.GetType(TypeString);
        }

        if (Type is not null) {
            builder.OpenComponent(1, Type);

            if (parameters is not null) {
                builder.AddMultipleAttributes(2, parameters);
            }
            builder.CloseComponent();
        }
        base.BuildRenderTree(builder);
    }
}

来自repo

【讨论】:

  • 这看起来确实不错,但是如何从我的组件实例中获取现有参数作为 Dictionary 以将其传递给 BuildRenderTree?
  • @Dagovax 它有一个名为Values 的参数,即Dictionary&lt;string,string&gt;。如果你返回提交,你会看到它是ParametersDictionary&lt;string,object&gt;。我被要求将其更改为 用于一个用例。如果你运行演示,你会看到我传递了不同的参数。
  • 我正要发布一个非常相似的答案,但布赖恩打败了我。要回答您的问题,您不能“渲染”组件的现有实例。 Renderer 实例化提供的type,在将其附加到渲染树时调用Attach,然后通过调用SetParametersAsync 传入参数。
  • 正如@MrCakaShaunCurtis 所指出的,组件的关键是代码块底部的最后一个if 块。
  • 您还应该测试定义的Type 实现IComponent - 所有渲染组件都必须实现此接口。 if (!Type.GetInterfaces().Contains(typeof(IComponent))) throw new Exception($" {component.ComponentType.Name} must implement IComponent."); 之类的东西。
猜你喜欢
  • 1970-01-01
  • 2020-07-20
  • 2020-06-11
  • 1970-01-01
  • 1970-01-01
  • 2020-01-04
  • 2020-11-04
  • 2020-12-29
  • 2020-07-17
相关资源
最近更新 更多