在自定义基础组件类中动态创建CascadingValue

时间:2020-09-04 14:45:34

标签: blazor blazor-server-side

我正在使用一个自定义基础组件类,每个自定义页面都继承自该基础类。

我没有任何剃须刀代码,因为它不会在我的基本组件类中进行模板化-仅应包含一些基本逻辑和初始化内容。

现在,我想包装一个级联值,因为在将嵌套在任何子级中的任何组件/页面上,都应该可以访问我的基类的属性值。我该怎么做,我试图在基本组件上伪造一些childContent,但是我没有工作

public class BaseComponent : ComponentBase
{
    [Parameter] public RenderFragement ChildContent {get;set;}     
    protected override void OnInitialized()
    {
        ChildContent = b =>
        {
            b.OpenComponent<CascadingValue<IBvdDataComponent>>(0);
            b.AddAttribute(1, "Name", "DataComponent");
            b.AddAttribute(2, "Value", this);
            b.CloseComponent();
         };

    }
}


   My page component:

@page "/anypage"
@inherits BaseComponent

    <div>
        <MyNestedComponent />
    </div>

我想在MyNestedComponent中做

[CascadingParameter]
public BaseComponent BaseComponent { get; set; }

什么是正确的方法?

2 个答案:

答案 0 :(得分:1)

如果您乐于使用一些反射功能,则有可能。

public class MyBase : ComponentBase
{
    string someValue = "test";
    public MyBase()
    {
        var rf = typeof(ComponentBase).GetField("_renderFragment", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        var pqr= typeof(ComponentBase).GetField("_hasPendingQueuedRender", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        var nr= typeof(ComponentBase).GetField("_hasNeverRendered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        rf.SetValue(this, (RenderFragment)(builder =>
        {
            pqr.SetValue(this, false);
            nr.SetValue(this, false);
            builder.OpenComponent<CascadingValue<string>>(1);
            builder.AddAttribute(2, "Value", someValue);
            builder.AddAttribute(3, "ChildContent", (RenderFragment)( builder2 => BuildRenderTree(builder2)));
            builder.CloseComponent();
        }));
    }
}

这将自动为所有子组件包括一个针对“ someValue”的CascadingValue。

如果您不想使用反射,则可以创建自己的基础组件来实现ComponentBase所做的所有事情,然后以类似的方式修改构造函数,但直接引用字段而不使用反射。 / p>

答案 1 :(得分:0)

我遇到了类似的情况,我需要在 Base Component 类中创建一个 CascadingValue,因为我想要对父级的引用并允许自定义 HTML 标签,我想知道如何实现这一点的唯一方法是手动构建组件树,但我没有在 Base 构造函数中使用 Reflection,而是使用了 BuildRenderTree(RenderTreeBuilder builder) 方法。

public class Panel : ComponentBase
{
  [CascadingParameter]
  public Panel ParentPanel { get; set; }

  [Parameter]
  public RenderFragment ChildContent { get; set; }

  [Parameter]
  public string Tag { get; set; } = "div";
      
  protected override void BuildRenderTree(RenderTreeBuilder builder)
  {
     base.BuildRenderTree(builder);

     // Add the panel element
     builder.OpenElement(0, Tag);

     // Add the CascadingValue component
     builder.OpenComponent<CascadingValue<Panel>>(1);
     builder.AddAttribute(2, "Value", this);

     // Need to add the ChildContent attribute first then add the actual ChildContent component
     // using a callback
     builder.AddAttribute(3, "ChildContent", (RenderFragment)((builder2) => {
        builder2.AddContent(4, ChildContent);
     }));

     builder.CloseComponent();  // Close the CascadingValue
     builder.CloseElement();    // Close the Tag element
  }
}