从 Blazor 中的页面组件调用 MainLayout 中的方法

Call method in MainLayout from a page component in Blazor

我有一个带有 MainLayout 页面的 Blazor 应用程序,它有一个 @Body 来加载实际页面内容。

在我的例子中 Index.razor 被加载到 MainLayout 页面中。

有没有办法从父页面中的子页面 (Index.razor) 调用方法? MainLayout.razor?

示例:

MainLayout.razor

<div class="content">
<ul class="menu">
  <li>menu item 1</li>
</ul>

@Body

</div>

@code
{
    public async Task Test()
    {
        await JsRuntime.InvokeAsync<object>("console.log", "test parent");
    }
}

Index.razor

<h1>This is the index page</h1>
<button @onclick="(async () => await btn_clicked())">Call parent method</button>

@code
{
    // Call method in MainLayout
    public async Task btn_clicked()
    {
        await parent.Test();
    }
}

您可以结合级联值和 EventCallback 来完成此操作。

首先,为您的 Test 创建事件回调。为此,请在 MainLayout.razor 中添加以下代码。

EventCallback btn_clicked => EventCallback.Factory.Create(this, Test);

或者,要确保只创建此 object 一次,您可以使用以下内容:

EventCallback _btn_clicked = EventCallback.Empty;
EventCallback btn_clicked  {
    get {
        if (_btn_clicked.Equals(EventCallback.Empty))
            _btn_clicked = EventCallback.Factory.Create(this, Test);
        return _btn_clicked;
    }
}

接下来,确保将此事件回调级联到 body。

<CascadingValue Value=btn_clicked >
    @Body
</CascadingValue>

现在,在您的 Index.razor 代码中,设置 属性:

[CascadingParameter]
public EventCallback btn_clicked { get; set; }

谢谢。第一个答案正是我需要的,虽然我需要传入一个参数,所以它与布局相同,除了:

在MainLayout.razor中:

public EventCallback<string> EventName => EventCallback.Factory.Create<string>(this, MethodName);

在Index.razor中:

[CascadingParameter]
protected EventCallback<string> EventName { get; set; }

调用方法:

EventName.InvokeAsync("Name");

回调方法有效,但仍然相当有限,我采用的方法是使用从 Xamarin.Forms...

克隆的“消息中心”

https://github.com/aksoftware98/blazor-utilities

https://www.nuget.org/packages/AKSoftware.Blazor.Utilities/

https://youtu.be/HdEJ4GD9hwM

它非常简单、灵活,并且更像一个跨组件的 pubsub 消息传递系统,这有很多好处。

因此,无论嵌套状态和位置如何,您都可以将事件“广播”到单个或多个组件 - 非常灵活且有用。取自他们的文档...

在您的 _imports.razor

中放置一个 using
@using AKSoftware.Blazor.Utilities

然后在 MainLayout.razor

中添加订阅者
public void SubscribeToMessage()
{
    MessagingCenter.Subscribe<Component1, string>(this, "greeting_message", 
(sender, value) => 
    {
    // Do actions against the value 
    // If the value is updating the component make sure to call 
    string greeting = $"Welcome {value}";
    StateHasChanged(); // To update the state of the component 
    });
}

以及您想要的任何组件中的发布者

public void SendMessage()
{
 string valueToSend = "Hi from Component 1";
 MessagingCenter.Send(this, "greeting_message", valueToSend);
}

您可以将订阅者和发件人放在组件的任意组合中。我一直在做一个实时日期同时更新多个组件的项目,这是一个很好的解决方案,它允许我将所有集线器连接逻辑放在 MainLayout.razor 中,然后调用并响应所有根据需要添加组件,防止创建多个集线器连接,并与级联状态协同工作。