在 Blazor 中的 Page 和 NavMenu 之间交换数据

Ole*_*ers 5 c# razor-pages blazor blazor-server-side

我有一个标准 - blazor - 项目,其中包含以下组件:

-> MainLayout.razor
-> NavMenu.razor
-> Pages/Index.razor
-> Pages/Sub1.razor
Run Code Online (Sandbox Code Playgroud)

MainLayout 看起来像这样:

<div class="sidebar">
    <NavMenu />
</div>
<div>@Body</div>
Run Code Online (Sandbox Code Playgroud)

现在我想在我的页面(index.razor、sub1.razor)和导航菜单之间交换数据,这样我就可以在导航菜单中添加这样的内容:

<div><p>You are now on Page: @CurrentPageName</p></div>
Run Code Online (Sandbox Code Playgroud)

如何直接从我的页面中设置 (navMenu).CurrentPageName?我希望为此使用静态类并不是一个好的选择。

Qua*_*ngo 6

更好的范围服务实现:

 public class CurrentPage
    {
        public string CurrentPageName { get; private set; }

        public void SetCurrentPageName(string name)
        {
            if (!string.Equals(CurrentPageName, name)) 
            {
                CurrentPageName = name;
                NotifyStateChanged();
            }
        }

        public event Action OnChange; // event raised when changed

        private void NotifyStateChanged() => OnChange?.Invoke();
    }
Run Code Online (Sandbox Code Playgroud)

我们不是在传递对象的字典,我们有一个做一件事的简单服务。更改页面的唯一方法是 call SetCurrentPageName,它会引发一个事件让消费者知道名称已更改。这在非嵌套组件之间是必需的,因为更新不会传播。

我们还需要在启动时注册服务(因为当前页面是特定于会话的):

            services.AddScoped<CurrentPage>();
Run Code Online (Sandbox Code Playgroud)

我们将注入Index.razor并使用它:

@page "/"
@inject CurrentPage currentPage

<h1>Hello, world!</h1>

Welcome to your new app.
<button @onclick="ChangeName">Set Page Name</button>

<SurveyPrompt Title="How is Blazor working for you?" />
@code
{

    protected override void OnInitialized()
    {
        currentPage.SetCurrentPageName("The Home Page");
        base.OnInitialized();
    }

    void ChangeName() => currentPage.SetCurrentPageName("Name changed");
}
Run Code Online (Sandbox Code Playgroud)

最后在顶部NavMenu.razor

@inject CurrentPage currentPage
Run Code Online (Sandbox Code Playgroud)

再往下..


    <p>The current page is @currentPage.CurrentPageName</p>

@code {
    protected override void OnInitialized()
    {
        // if the OnChange event is raised, refresh this view
        currentPage.OnChange += () => StateHasChanged();

        base.OnInitialized();
    }
Run Code Online (Sandbox Code Playgroud)

这个状态类不知道它是如何使用的,也没有对象或引用被传递。

[编辑] 我决定用于设置页面名称的注入/覆盖模式相当 unBlazor,所以我还编写了一个组件来简化它 - PageName.razor:

@inject CurrentPage currentPage;

@code {
    [Parameter]
    public string Name { get; set; }

    protected override void OnParametersSet()
    {
        currentPage.SetCurrentPageName(Name);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在任何想要设置标题的页面都可以这样做:

@page "/fetchdata"
@inject HttpClient Http
<PageName Name="Weather forecast page!" />
Run Code Online (Sandbox Code Playgroud)

整个消费者现在是一个组件:)