最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - MainLayout and Sidebar rendermode in Blazor - Stack Overflow

programmeradmin1浏览0评论

My application is built with .NET 8 in Blazor. The configuration in the Program.cs is like this:

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();

I want to have a nice sidebar for it. I created a SidebarComponent that generates the sidebar quite nicely. This is the code of the component

@inject NavigationManager _navigationManager
@rendermode InteractiveAuto

<aside id="sidebar" class="sidebar break-point-sm has-bg-image @(_isCollapsed ? "collapsed" : "") @(_isToggled ? "toggled" : "")">
    <a @onclick="BtnCollapseClicked" id="btn-collapse" class="sidebar-collapser"><i class="ri-arrow-left-s-line"></i></a>
    <div class="image-wrapper">
    </div>
    <div class="sidebar-layout">
        <div class="sidebar-header">
            <div class="pro-sidebar-logo">
                <div>P</div>
                <h5>Pro Sidebar</h5>
            </div>
        </div>
        <div class="sidebar-content">
            <nav class="menu open-current-submenu">
                <ul>
                    <li class="menu-header"><span>BLAZOR</span></li>

                    @foreach (var menuItem in standardItems)
                    {
                        <MenuItemComponent MenuItem="@menuItem" MenuItemClickCallback="MenuItemClick" />
                    }
                </ul>
            </nav>
        </div>
    </div>
</aside>

@code {
    private bool _isCollapsed { get; set; } = false;
    private bool _isToggled { get; set; } = false;

    List<MenuItem> standardItems = SidebarData.GetStandardMenuItems();
    List<MenuItem> generalMenuItems = SidebarData.GetGeneralMenuItems();

    public void BtnToggleClicked()
    {
        _isToggled = !_isToggled;
        StateHasChanged();
    }

    public void MouseClickedInOverlay()
    {
        if (_isToggled)
            _isToggled = false;
        generalMenuItems.ForEach(x => x.IsOpened = false);
        StateHasChanged();
    }

   // Omitted
}

Then in the MainLayout, I added

<div class="layout has-sidebar fixed-sidebar fixed-header">
    <SidebarComponent @ref="sideBarComponent"/>

    <div @onclick="@(e => sideBarComponent?.MouseClickedInOverlay())" id="overlay" class="overlay"></div>
    <div class="layout">
    <!-- Omitted -->
    </div>
</div>

When the application starts, I get this error:

System.InvalidCastException: 'Unable to cast object of type 'Microsoft.AspNetCore.Components.Endpoints.SSRRenderModeBoundary' to type 'HypnoPlatform.Client.Pages.Shared.Sidebar.SidebarComponent'.'

How can I call methods from the MainLayout to the SidebarComponent?

My application is built with .NET 8 in Blazor. The configuration in the Program.cs is like this:

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();

I want to have a nice sidebar for it. I created a SidebarComponent that generates the sidebar quite nicely. This is the code of the component

@inject NavigationManager _navigationManager
@rendermode InteractiveAuto

<aside id="sidebar" class="sidebar break-point-sm has-bg-image @(_isCollapsed ? "collapsed" : "") @(_isToggled ? "toggled" : "")">
    <a @onclick="BtnCollapseClicked" id="btn-collapse" class="sidebar-collapser"><i class="ri-arrow-left-s-line"></i></a>
    <div class="image-wrapper">
    </div>
    <div class="sidebar-layout">
        <div class="sidebar-header">
            <div class="pro-sidebar-logo">
                <div>P</div>
                <h5>Pro Sidebar</h5>
            </div>
        </div>
        <div class="sidebar-content">
            <nav class="menu open-current-submenu">
                <ul>
                    <li class="menu-header"><span>BLAZOR</span></li>

                    @foreach (var menuItem in standardItems)
                    {
                        <MenuItemComponent MenuItem="@menuItem" MenuItemClickCallback="MenuItemClick" />
                    }
                </ul>
            </nav>
        </div>
    </div>
</aside>

@code {
    private bool _isCollapsed { get; set; } = false;
    private bool _isToggled { get; set; } = false;

    List<MenuItem> standardItems = SidebarData.GetStandardMenuItems();
    List<MenuItem> generalMenuItems = SidebarData.GetGeneralMenuItems();

    public void BtnToggleClicked()
    {
        _isToggled = !_isToggled;
        StateHasChanged();
    }

    public void MouseClickedInOverlay()
    {
        if (_isToggled)
            _isToggled = false;
        generalMenuItems.ForEach(x => x.IsOpened = false);
        StateHasChanged();
    }

   // Omitted
}

Then in the MainLayout, I added

<div class="layout has-sidebar fixed-sidebar fixed-header">
    <SidebarComponent @ref="sideBarComponent"/>

    <div @onclick="@(e => sideBarComponent?.MouseClickedInOverlay())" id="overlay" class="overlay"></div>
    <div class="layout">
    <!-- Omitted -->
    </div>
</div>

When the application starts, I get this error:

System.InvalidCastException: 'Unable to cast object of type 'Microsoft.AspNetCore.Components.Endpoints.SSRRenderModeBoundary' to type 'HypnoPlatform.Client.Pages.Shared.Sidebar.SidebarComponent'.'

How can I call methods from the MainLayout to the SidebarComponent?

Share Improve this question edited 2 days ago marc_s 755k184 gold badges1.4k silver badges1.5k bronze badges asked 2 days ago EnricoEnrico 6,2149 gold badges77 silver badges175 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

I recall stumbling into this previously. I think the issue is that the line:

<SidebarComponent @ref="sideBarComponent"/>

is, unintuitively, trying to assign an SSRRenderModeBoundary to the variable sideBarComponent, instead of a SidebarComponent. Something to do with the framework wrapping the component with SSRRenderModeBounday when using InteractiveAuto.

I never really got to the bottom of it, but using a shared service to communicate was my solution. Something like:

public class SidebarStateService
{
    public event Action? OnOverlayClicked;

    public void OverlayClicked()
    {
        OnOverlayClicked?.Invoke();
    }
}

Then inject this into both your MainLayout and Sidebar.

Call OverlayClicked from MainLayout and hookup to OnOverlayClicked in your Sidebar.,

发布评论

评论列表(0)

  1. 暂无评论