Add LayoutDisplay component and use it in StandaloneApp
This commit is contained in:
parent
f54df27c21
commit
69498f68f9
|
|
@ -0,0 +1,2 @@
|
|||
@using Microsoft.AspNetCore.Blazor.Layouts
|
||||
<c:LayoutDisplay Page=@typeof(StandaloneApp.Pages.Home) />
|
||||
|
|
@ -1 +0,0 @@
|
|||
<h1>Hello, world!</h1>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@(Layout<StandaloneApp.Shared.MainLayout>())
|
||||
<h1>Hello, world!</h1>
|
||||
|
|
@ -9,7 +9,7 @@ namespace StandaloneApp
|
|||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
new BrowserRenderer().AddComponent<Home>("app");
|
||||
new BrowserRenderer().AddComponent<App>("app");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
@using Microsoft.AspNetCore.Blazor.RenderTree
|
||||
@(Implements<Microsoft.AspNetCore.Blazor.Layouts.ILayoutComponent>())
|
||||
|
||||
<fieldset>
|
||||
<legend>Layout</legend>
|
||||
@Body
|
||||
</fieldset>
|
||||
|
||||
@functions {
|
||||
public RenderFragment Body { get; set; }
|
||||
}
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<BlazorBuildExe>dotnet "$(MSBuildThisFileDirectory)../tools/Microsoft.AspNetCore.Blazor.Build.dll"</BlazorBuildExe>
|
||||
|
||||
<!-- The Blazor build code can only find your referenced assemblies if they are in the output directory -->
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="RazorCompilation.targets" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
using Microsoft.AspNetCore.Blazor.RenderTree;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Layouts
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays the specified page component, rendering it inside its layout
|
||||
/// and any further nested layouts.
|
||||
/// </summary>
|
||||
public class LayoutDisplay : IComponent
|
||||
{
|
||||
private RenderHandle _renderHandle;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the page component to display.
|
||||
/// The type must implement <see cref="IComponent"/>.
|
||||
/// </summary>
|
||||
public Type Page { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Init(RenderHandle renderHandle)
|
||||
{
|
||||
_renderHandle = renderHandle;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetParameters(ParameterCollection parameters)
|
||||
{
|
||||
parameters.AssignToProperties(this);
|
||||
Render();
|
||||
}
|
||||
|
||||
private void Render()
|
||||
{
|
||||
// In the middle, we render the requested page
|
||||
var fragment = RenderComponentWithBody(Page, bodyParam: null);
|
||||
|
||||
// Repeatedly wrap it in each layer of nested layout until we get
|
||||
// to a layout that has no parent
|
||||
Type layoutType = Page;
|
||||
while ((layoutType = GetLayoutType(layoutType)) != null)
|
||||
{
|
||||
fragment = RenderComponentWithBody(layoutType, fragment);
|
||||
}
|
||||
|
||||
_renderHandle.Render(fragment);
|
||||
}
|
||||
|
||||
private RenderFragment RenderComponentWithBody(Type componentType, RenderFragment bodyParam) => builder =>
|
||||
{
|
||||
builder.OpenComponent(0, componentType);
|
||||
if (bodyParam != null)
|
||||
{
|
||||
builder.AddAttribute(1, nameof(ILayoutComponent.Body), bodyParam);
|
||||
}
|
||||
builder.CloseComponent();
|
||||
};
|
||||
|
||||
private Type GetLayoutType(Type type)
|
||||
=> type.GetCustomAttribute<LayoutAttribute>()?.LayoutType;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue