Dynamically create CascadingValue in custom base component class

雨燕双飞 提交于 2021-01-28 11:09:40

问题


I'm using a custom base component class from which every custom page inhertits from.

I do not have any razor code, because it won't be templated in my my base component class - it is only supposed to contain some base logics and intialization stuff.

Now i want do wrap around a cascading value, because on any component/page which will be nested within any child level should get access to a property value of my base class. How can i do this, i tried to fake some childContent on the base component but i didnt work

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>

In MyNestedComponent I want to do:

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

Whats the correct way to do this.


回答1:


If you are happy to use a bit of reflection, it is possible.

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();
        }));
    }
}

This will automatically include a CascadingValue for "someValue" to all child components.

If you don't want to use reflection, you can create your own base component that implements everything ComponentBase does, then modify the constructor in a similar way, but directly referencing the fields instead of using reflection.




回答2:


I had a similar situation where I needed to create a CascadingValue in a Base Component class because I wanted a reference to the Parent and allow custom HTML tags, only way I could figure out how to achieve this was to manually build the component tree, but instead of using Reflection in the Base constructor I used the BuildRenderTree(RenderTreeBuilder builder) method.

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
  }
}


来源:https://stackoverflow.com/questions/63743386/dynamically-create-cascadingvalue-in-custom-base-component-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!