【问题标题】:Passing method to component将方法传递给组件
【发布时间】:2019-11-11 20:24:24
【问题描述】:

我一直在尝试找出可行的方法以及如何将方法从主页传递到 Blazor 中的组件。

我有一个简单的剃​​须刀页面,其中包含一个带有按钮的组件。我想将剃须刀页面中的onclick方法传递给组件中的按钮

注意:我不需要这个方法来返回任何 void 就可以了。我只需要能够从组件上的按钮中的主页调用方法。我只是在这里添加了 int 作为猜测,因为它在抱怨 T

页面

@page "/test"
@using Testing.Client.Model;
@using System.Threading;

<TestMethodPassing ExternalMethod="@btnClick"></TestMethodPassing>

@code {

    public Action<int> btnClick(){ return 1;}

}

组件模型

public class TestingMethodPassingModel : ComponentBase
{
    [Parameter]
    protected Action<int> ExternalMethod { get; set; }
}

组件

@inherits TestingMethodPassingModel;
@using testing.Client.Model;
@using System.Threading;


<button class="btn btn-primary" @onclick="@ExternalMethod" autofocus>External button</button>


@code {


    }

错误

上面的代码给了我以下错误

“btnClick”与委托“Action”没有重载

我也尝试过使用 T 类型,但由于 Blazor 出于某种原因无法找到类型 T 的引用而失败了

更新说明

从答案拼凑而成的工作示例。 PassingMethodToComponent

【问题讨论】:

  • 我不太了解 razor,但我很确定 onclick-delegate 不会期望 int-argument。
  • 我已经创建了您的示例,它给出了 CS1503 Argument 2: cannot convert from 'System.Action&lt;int&gt;' to 'Microsoft.AspNetCore.Components.EventCallback 错误。还有CS0428 Cannot convert method group 'btnClick' to non-delegate type 'object'. Did you intend to invoke the method?.
  • 您的代码并未真正显示您希望如何/在何处使用返回值。
  • 同样return 1; 也不会编译 - CS0029 Cannot implicitly convert type 'int' to 'System.Action&lt;int&gt;'
  • 此时我并没有真正参加任何活动,我一直在努力让它发挥作用。我真的不需要该方法来返回任何我只需要能够通过它的东西。 Gitter 上的某个人说要使用 T,但它没有用,所以我抓住了稻草,假设它需要一个 return var。您的右键 Onclick 不需要返回 var

标签: c# .net-core blazor


【解决方案1】:

这是一个将方法从父级传递给子级并由子级调用的示例。由于您不需要返回值,因此我只使用Action 而不是Action&lt;T&gt;

有很多方法可以使这段代码更紧凑,但我已经找到了一个更详细的示例,希望能更好地展示正在发生的事情。

父组件:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<Child ParentMethod="@SayHello" />

@code {

    private void SayHello()
    {
        Console.WriteLine("Hello!");
    }

}

子组件:

<h3>Child</h3>

<button @onclick="@InvokeParentMethod">Click Me!</button>

@code {

[Parameter] public Action ParentMethod { get; set; }

private void InvokeParentMethod()
{
    ParentMethod?.Invoke();
}

}

【讨论】:

  • 我必须公开一些东西才能让它工作。但是谢谢我喜欢这个选项
  • 如何从子进程向 SayHello 函数发送参数?
  • 对于 async 函数,只需传递 Task
【解决方案2】:

这是因为 btnClick 的 Click 事件不是 Action&lt;int&gt; 类型,而是实际上是 EventCallback&lt;TIn&gt;。所以改变你需要改变一些事情。

将外部方法更改为

[Parameter]
protected EventCallback<int> ExternalMethod {get; set;}

并将 btnClick 更改为

public void btnClick(int param) { /* code */ }
// and then set the razor to
<TestMethodPassing ExternalMethod="@btnClick"></TestMethodPassing>

// Or do it with a lambda in the razor

<TestMethodPassing ExternalMethod="@((param) => {/* code */ })"></TestMethodPassing>

有一个 GitHub 问题跟踪新的事件处理和绑定here

【讨论】:

  • 正确。但是在 onClick 和参数之间添加一个InternalMethod() 可能更符合要求。
  • 我使用了 void 选项:无法从 'System.Action' 转换为 'Microsoft.AspNetCore.Components.EventCallback'
  • @DaImTo 我刚刚重写了我的问题
  • 那么除了内联之外没有办法传递方法吗?
  • 查看@chris-sainty 的回答,这会更好地满足您的需求
【解决方案3】:

这应该可行:

页面:

<TestMethodPassing ExternalMethod="@btnClick"></TestMethodPassing>
<label>@something</label>

@code {

    string something = "1";

    void btnClick()
    {
        something = "11";
    }
}

TestingMethodPassingModel:

[Parameter]
protected Action ExternalMethod { get; set; }

组件:

<button class="btn btn-primary" @onclick="@ExternalMethod" autofocus>External button</button>

对于你的例子(Action&lt;int&gt;):

页面:

<TestMethodPassing ExternalMethod="@btnClick"></TestMethodPassing>

@code {

    void btnClick(int arg)
    {

    }
}

TestingMethodPassingModel:

[Parameter]
protected Action<int> ExternalMethod { get; set; }

组件:

<button class="btn btn-primary" @onclick="@ClickHandler" autofocus>External button</button>

@code {
    void ClickHandler()
    {
        ExternalMethod.Invoke(10);
    }
}

【讨论】: