Blazor .NET 8 — панель FluentDialogProvider не отображается

Я пытаюсь заставить FluentDialogProvider работать, чтобы он отображал панель. Это ошибка, которую я получаю:

warn: Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer[100]
      Unhandled exception rendering component: <FluentDialogProvider /> needs to be added to the main layout of your application/site. (Parameter 'OnShowAsync')      System.ArgumentNullException: <FluentDialogProvider /> needs to be added to the main layout of your application/site. (Parameter 'OnShowAsync')
         at Microsoft.FluentUI.AspNetCore.Components.DialogService.ShowDialogAsync[TData](Type dialogComponent, TData data, DialogParameters parameters) in /_/src/Core/Components/Dialog/Services/DialogService-Dialog.cs:line 17
         at Microsoft.FluentUI.AspNetCore.Components.DialogService.ShowPanelAsync[TDialog](Object data, DialogParameters parameters) in /_/src/Core/Components/Dialog/Services/DialogService-Dialog.cs:line 56
         at S2IX.NodeManager.UI.Web.Shared.Nodes.NodeSnapshots.OpenPanelRightAsync(Guid server) in E:\repos\nodemanager\NodeManager\S2IX.NodeManager.UI.Web\Shared\Nodes\NodeSnapshots.razor:line 108
         at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
         at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
fail: Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost[111]
      Unhandled exception in circuit 'BvKsO6dDjcGDj2ubE1pbKa4oPkFQ1ZRukm-frbIFvGI'.
      System.ArgumentNullException: <FluentDialogProvider /> needs to be added to the main layout of your application/site. (Parameter 'OnShowAsync')
         at Microsoft.FluentUI.AspNetCore.Components.DialogService.ShowDialogAsync[TData](Type dialogComponent, TData data, DialogParameters parameters) in /_/src/Core/Components/Dialog/Services/DialogService-Dialog.cs:line 17
         at Microsoft.FluentUI.AspNetCore.Components.DialogService.ShowPanelAsync[TDialog](Object data, DialogParameters parameters) in /_/src/Core/Components/Dialog/Services/DialogService-Dialog.cs:line 56
         at S2IX.NodeManager.UI.Web.Shared.Nodes.NodeSnapshots.OpenPanelRightAsync(Guid server) in E:\repos\nodemanager\NodeManager\S2IX.NodeManager.UI.Web\Shared\Nodes\NodeSnapshots.razor:line 108
         at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
         at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

Я зарегистрировал компоненты в своем Startup.cs, а также добавил DialogueService в соответствии с областью действия. Он также находится в моем MainLayout.cs в этом разделе. Не совсем понимаю, что здесь происходит, поскольку мне кажется, что я правильно следовал документации.

Программа.cs:

builder.Services.AddScoped<DialogService>();
builder.Services.AddFluentUIComponents();

Mainlayout.cs:

@inherits LayoutComponentBase
@using S2IX.NodeManager.UI.Web.Shared.CommandBars
@using S2IX.NodeManager.Models

<FluentLayout Style = "display: flex; height: auto;">
    <FluentHeader style = "background-color:#29ABE2; height: 75px;">
        <img src = "/Images/s2ixbrand.png" alt = "S2IX" />
    </FluentHeader>

    <FluentBodyContent>
        <FluentStack Orientation = "Orientation.Horizontal" Style = "justify-content: space-between; ">
            @if (collapseMenu)
            {
                <FluentStack Orientation = "Orientation.Vertical" Style = "width: auto; height: 100vh;">
                    <NavMenu />
                </FluentStack>
            }
            <main style = "width:auto;">
                <div class = "content">
                    <article id = "article">
                        <AppCommandBar />
                        @Body
                    </article>
                </div>
                <FluentToastProvider MaxToastCount = "5" Position = "ToastPosition.BottomRight" RemoveToastsOnNavigation = "true" />
                <FluentDialogProvider />
                <FluentTooltipProvider />
                <FluentMessageBarProvider />
            </main>
        </FluentStack>
    </FluentBodyContent>

</FluentLayout>



@code {
        bool collapseMenu = true;

        void ToggleMenu()
        {
            collapseMenu = !collapseMenu;
            StateHasChanged();
        }
}

NodeSnapshots.cs:

@inject ApplicationStateService stateService
@inject NavigationManager navMan
@inject IDialogService DialogService

@rendermode RenderMode.InteractiveServer


@if (!nodesFound)
{
    @if (!showDialog)
    {
        <FluentProgressRing>Loading Nodes...</FluentProgressRing>
    }
    else
    {
        <p>No Nodes found</p>
    }
}
else
{
    <FluentDataGrid Items = "@FilteredItems" ResizableColumns = "false" Pagination = "@pagination" Style = "overflow:auto;">
        <PropertyColumn Title = "Name" Property = "@(n => n.Name)" Sortable = "true">
            <ColumnOptions>
                <div class = "search-box">
                    <FluentSearch type = "search" Autofocus = "true" @bind-Value=nodeFilter @oninput = "HandleNameFilter" @bind-Value:after = "HandleClear" Placeholder = "Node name..." />
                </div>
            </ColumnOptions>
        </PropertyColumn>
        <PropertyColumn Title = "Description" Property = "@(n => n.Description)" Sortable = "false" />
        <TemplateColumn Title = "Servers" Align = "Align.Start">
            <p @onclick = "@(() => OpenPanelRightAsync(@context.Servers[0]))">@context.Servers.Count</p>
        </TemplateColumn>
        <TemplateColumn Title = "" Align = "Align.Start">
            <FluentIcon Value = "@(new Icons.Regular.Size24.Edit())" OnClick = "@(() => Edit(@context))" />
        </TemplateColumn>
    </FluentDataGrid>

}



@code {
    // UI
    private PaginationState pagination = new PaginationState { ItemsPerPage = 20 };
    private bool showDialog = false;
    private IDialogReference? _dialog;

    // Nodes
    IQueryable<S2IXNodeDto>? nodesGrid;
    bool nodesFound = false;

    // Filter
    string nodeFilter = string.Empty;
    IQueryable<S2IXNodeDto>? FilteredItems => nodesGrid?.Where(n => n.Name.Contains(nodeFilter, StringComparison.CurrentCultureIgnoreCase));

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            stateService.SetAddNode(false);
            stateService.SetEditNode(false);
            stateService.SetAddSelectedNode(null);

            using (HttpClient httpClient = new HttpClient())
            {
                NodeClient nodeClient = new NodeClient(httpClient);
                var result = await nodeClient.GetAllNodes();

                nodesGrid = result.OrderBy(n => n.Name).AsQueryable();
                nodesFound = nodesGrid.Any();

                if (!nodesFound)
                {
                    showDialog = true;
                }
            }
        }
        StateHasChanged();
    }

    private void Edit(S2IXNodeDto nodeDto)
    {
        stateService.SetAddSelectedNode(nodeDto);
        stateService.SetEditNodeNetwork(true);
        navMan.Refresh(true);
    }
    private void HandleClear()
    {
        if (string.IsNullOrEmpty(nodeFilter))
        {
            nodeFilter = string.Empty;
        }
    }
    private void HandleNameFilter(ChangeEventArgs args)
    {
        if (args.Value is string value)
        {
            nodeFilter = value;
        }
    }
    private async Task OpenPanelRightAsync(Guid server)
    {
        using (HttpClient httpClient = new HttpClient())
        {
            ServerClient serverClient = new ServerClient(httpClient);
            ServerDto result = await serverClient.GetServer(server.ToString());

            _dialog = await DialogService.ShowPanelAsync<SimpleServerPanel>(result, new DialogParameters<ServerDto>()
            {
                Content = result,
                Title = $"Hello {result.Name}",
                Alignment = HorizontalAlignment.Right,
                PrimaryAction = "Close"
            });
            DialogResult panel = await _dialog.Result;
            HandlePanel(panel);
        }
    }

    private static void HandlePanel(DialogResult result)
    {
        if (result.Cancelled)
        {
            return;
        }

        if (result.Data is not null)
        {
            var server = result.Data as ServerDto;
            return;
        }
    }
}

SimpleServerPanel.razor:

@implements IDialogContentComponent<ServerDto>

<FluentDialogBody>
    <h3>Servers</h3>

    <FluentTextField @bind-Value = "@Content.Name">This is a test:</FluentTextField>

</FluentDialogBody>



@code 
{
    [Parameter]
    public ServerDto Content { get; set; } = default!;
}

Любая помощь будет принята с благодарностью!

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
273
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ответ заключался в том, что в моем MainLayout мне пришлось добавить @rendermode = "RenderMode.InteractiveServer" к FluentDialogProvider, например:

<FluentDialogProvider @rendermode = "RenderMode.InteractiveServer"/>

Жаль, что в документации об этом не упомянуто.

Собственно, это задокументировано. fluentui-blazor.net/DialogService

Gary Chan 16.05.2024 20:25

Другие вопросы по теме