Add LayoutDisplay component and use it in StandaloneApp

This commit is contained in:
Steve Sanderson 2018-02-16 14:54:30 +00:00
parent f54df27c21
commit 69498f68f9
7 changed files with 86 additions and 2 deletions

View File

@ -0,0 +1,2 @@
@using Microsoft.AspNetCore.Blazor.Layouts
<c:LayoutDisplay Page=@typeof(StandaloneApp.Pages.Home) />

View File

@ -1 +0,0 @@
<h1>Hello, world!</h1>

View File

@ -0,0 +1,2 @@
@(Layout<StandaloneApp.Shared.MainLayout>())
<h1>Hello, world!</h1>

View File

@ -9,7 +9,7 @@ namespace StandaloneApp
{
public static void Main(string[] args)
{
new BrowserRenderer().AddComponent<Home>("app");
new BrowserRenderer().AddComponent<App>("app");
}
}
}

View File

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

View File

@ -1,6 +1,9 @@
<Project>
<PropertyGroup>
<BlazorBuildExe>dotnet &quot;$(MSBuildThisFileDirectory)../tools/Microsoft.AspNetCore.Blazor.Build.dll&quot;</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" />

View File

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