Layout 将blazor RenderFragment模板化为页面或组件中的布局

Layout 将blazor RenderFragment模板化为页面或组件中的布局,layout,rendering,blazor,Layout,Rendering,Blazor,我想在blazor的布局页面中有可自定义的内容。我曾尝试向布局中添加renderfragment参数,并在组件中添加具有相同名称的化妆,但未在布局中渲染 乙二醇 但是头部内容在身体中呈现。有谁能解释一下怎么做,或者为什么在布局中不可能这样做。我发现唯一可行的方法是,如果我在渲染片段中更改绑定参数,它将不会刷新内容 灵活内容 在导航时清除 无需任何接线即可更新 mainplayout.razor.cs 用法 灵活内容 在导航时清除 无需任何接线即可更新 mainplayout.razor.cs 用

我想在blazor的布局页面中有可自定义的内容。我曾尝试向布局中添加renderfragment参数,并在组件中添加具有相同名称的化妆,但未在布局中渲染

乙二醇

但是头部内容在身体中呈现。有谁能解释一下怎么做,或者为什么在布局中不可能这样做。我发现唯一可行的方法是,如果我在渲染片段中更改绑定参数,它将不会刷新内容

灵活内容 在导航时清除 无需任何接线即可更新 mainplayout.razor.cs

用法 灵活内容 在导航时清除 无需任何接线即可更新 mainplayout.razor.cs

用法
前面的答案很接近,但对我来说不起作用。 我就是这样解决的:

主要布局:

在任何页面中使用:


现在只剩下一个问题。。。当你更改页面时,你必须在该页面中输入一个空的,以便将其清除

前面的答案非常接近,但对我来说不起作用。 我就是这样解决的:

主要布局:

在任何页面中使用:


现在只剩下一个问题。。。当你更改页面时,你必须在该页面中添加一个空白以便清除它

布赖恩·帕克的回答对我来说非常有效。但是,我需要两个标题片段,因此无法使用默认的ChildContent命名

主要布局:

用法:


布赖恩·帕克的回答对我来说非常有效。但是,我需要两个标题片段,因此无法使用默认的ChildContent命名

主要布局:

用法:


无法更新属性。你必须调用一个函数,就像我必须设置片段一样,然后调用状态改变了。事实上,直接更新属性应该会给你一个警告。嗨,谢谢你的帮助。是的,上面的伪代码不起作用。我希望找到一种方法,当版面设置器中的内容发生更改时,触发标题重新呈现。此时,呈现的内容在布局中是静态的,因此如果我更改属性,它只会更新内容,而不会更新布局。我向该页面添加了另一个解决方案。有点复杂,但我对结果很满意。你不能更新属性。你必须调用一个函数,就像我必须设置片段一样,然后调用状态改变了。事实上,直接更新属性应该会给你一个警告。嗨,谢谢你的帮助。是的,上面的伪代码不起作用。我希望找到一种方法,当版面设置器中的内容发生更改时,触发标题重新呈现。此时,呈现的内容在布局中是静态的,因此如果我更改属性,它只会更新内容,而不会更新布局。我向该页面添加了另一个解决方案。有点复杂,但我对结果很满意。
layout.razor:

<header>
    @HeaderContent
</header>
@body

@code
{
[Parameter] public RenderFragment HeaderContent { get; set; }

}
component.razor:

<HeaderContent>
<p>my page specific content</p>
</HeaderContnt>
@inherits LayoutComponentBase

...
    <div class="top-row px-4">
        @headerContent
    </div>

    <div class="content px-4">
        <CascadingValue Value="this">
            @Body
        </CascadingValue>
    </div>
...
@code {
    RenderFragment headerContent => setHeader?.ChildContent;
    SetHeader setHeader;

    public void SetHeader(SetHeader setHeader)
    {
        this.setHeader = setHeader;
        Update();
    }

    public void Update() => StateHasChanged();
}
public class SetHeader : ComponentBase, IDisposable
{
    [CascadingParameter]
    public MainLayout MainLayout { get; set; }

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

    protected override void OnInitialized()
    {
        MainLayout.SetHeader(this);
        base.OnInitialized();
    }

    protected override bool ShouldRender()
    {
        var shouldRender = base.ShouldRender();
        if (shouldRender)
        {
            MainLayout.Update();
        }
        return base.ShouldRender();
    }

    public void Dispose()
    {
        MainLayout?.SetHeader(null);
    }
}
<SetHeader>
    <p>Current count: @currentCount</p>
</SetHeader>

<div class="main">
    <div class="top-row px-4">
        @headerContent
        @*<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>*@
    </div>
    <div class="content px-4">
        <CascadingValue Value="this">
            @Body
        </CascadingValue>
    </div>
</div>
@code {
    RenderFragment headerContent => setHeader?.ChildContent;
    SetHeader setHeader;

    public void SetHeader(SetHeader setHeader)
    {
        if (setHeader == null) return;

        this.setHeader = setHeader;
        this.setHeader.OnChange += StateHasChanged;
    }
}
public class SetHeader : ComponentBase, IDisposable
    {
        [CascadingParameter] public MainLayout MainLayout { get; set; }
        [Parameter] public RenderFragment ChildContent { get; set; }
        
        public event Action OnChange;
        protected override void OnInitialized()
        {
            MainLayout.SetHeader(this);
            Update();
            base.OnInitialized();
        }

        public void Update()
        {
            OnChange?.Invoke();
            StateHasChanged();
        }

        
        public void Dispose()
        {
            MainLayout?.SetHeader(null);
        }

    }
<SetHeader @ref="@setHeader">
    <p>Current count: @currentCount</p>

    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

</SetHeader>
SetHeader setHeader;

    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
        setHeader.Update();
    }
  <div class="main">
    <div class="top-row px-4">
        @FirstHeader
      
    </div>
   <div class="top-row px-4">
        @SecondHeader
       
    </div>
    <div class="content px-4">
        <CascadingValue Value="this">
            @Body
        </CascadingValue>
    </div>
</div>
@code 
{
   RenderFragment FirstHeader => _setHeader?.FirstHeaderTemplate;
   RenderFragment SecondHeader => _setHeader?.SecondHeaderTemplate;

   SetHeader _setHeader;

   public void SetHeader(SetHeader setHeader)
   {
       _setHeader = setHeader;
       Update();
   }

   public void Update() => StateHasChanged();
}
public class SetHeader : ComponentBase, IDisposable
    {
        [CascadingParameter]
        public MainLayout MainLayout { get; set; }

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

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

        protected override void OnInitialized()
        {
            MainLayout.SetHeader(this);
            base.OnInitialized();
        }

        protected override bool ShouldRender()
        {
            var shouldRender = base.ShouldRender();
            if (shouldRender)
            {
                MainLayout.Update();
            }
            return base.ShouldRender();
        }

        public void Dispose()
        {
            MainLayout?.SetHeader(null);
        }
    }
<SetHeader>
    <FirstHeaderTemplate>
         <LoginDisplay />
    </FirstHeaderTemplate>
    <SecondHeaderTemplate>
        <p>Current count: @currentCount</p>
    </SecondHeaderTemplate>
</SetHeader>