【问题标题】:How do I call a method in one Blazor (parent) component from another Blazor ("child") component?如何从另一个 Blazor(“子”)组件调用一个 Blazor(父)组件中的方法?
【发布时间】:2021-06-10 15:55:19
【问题描述】:

我正在构建我的第一个“真正的”Blazor 应用程序。目前,我正在开发一个搜索功能,它可以让用户查询 API 并获得答案。我觉得我真的很接近这一点,但我只需要一点方向。

DefaultSearch.razor 页面上,有一个文本输入绑定到String,它作为参数传递给“主”Blazor 组件(即Index.razor)。

我迷路的地方是如何从DefaultSearch.razor 页面上的按钮触发该过程。我有一个@onclick(doSomething),但我不知道在doSomething 方法中要做什么来启动该过程。

Index.razor:

@page "/"
@inject IHttpClientFactory clientFactory
<div class="text-center">
        @if (fetchedResults == null)
        {
            <HeaderLarge />
            <DefaultSearch />
        } else {
           <HeaderSmall />
           <SearchResultsPage FetchedResults="fetchedResults" />
        }
</div>

@code {
    [Parameter]
    public String queryString { get; set; }
    private async Task GetSearchResults()
    {
        try
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(@"http://192.168.1.234:8080");
            Search search = new Search(queryString);
            string searchstr = JsonConvert.SerializeObject(search);
            StringContent content = new StringContent(searchstr, Encoding.UTF8, "application/json");
            using HttpResponseMessage httpResponse = await client.PostAsync(("/api/...", content);
            httpResponse.EnsureSuccessStatusCode();
            if (httpResponse.StatusCode == System.Net.HttpStatusCode.OK)
            {
                string response = await httpResponse.Content.ReadAsStringAsync();
                fetchedResults = JsonConvert.DeserializeObject<SearchResultSet>(response);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

DefaultSearch.razor:

<div id="SearchContainer">
    <div id="SearchFormContainer">
        <input id="mainSearchInputField" name="queryString" type="text"  @bind="queryString" /><button @onclick()>Search</button>
    </div>
</div>

@code {
    public String queryString;

    public void doSomething(){
        // What do I do here?
    }
}

SearchResultsPage.razor:

<div>
    @if (FetchedResults != null)
    {
        @foreach (var result in FetchedResults.documents)
        {
            <div>
                <table class="message">
                    <tr>
                        <td>Subject</td>
                        <td>@(result.subject)</td>
                    </tr>
                    <tr>
                        <td>ID</td>
                        <td>@result.docId</td>
                    </tr>
                    <tr>
                        <td class="message_body" colspan="2">
                            <span>@(result.messageBody)</span>
                        </td>
                    </tr>
                </table>
            </div>
        }
    }
</div>

@code {
    [Parameter]
    public SearchResultSet FetchedResults { get; set; }
}

HeaderLarge.razor:

<h1> My Large Header </h1>

HeaderSmalal.razor:

<h5> My Small Header </h5>

【问题讨论】:

    标签: c# blazor-server-side .net-5


    【解决方案1】:

    在我看来,您的索引页面的整个代码体都在进行搜索,应该将其移至 DefaultSearch.razor 控件。所以DoSomething() 实际上应该是GetSearchResults()。确保将变量添加到 DefaultSearch.razor 以实际收集您的结果,并添加一个事件以将它们传递回父级:

    [Parameter]
    SearchResultSet fetchedResults {get; set;}
    
    [Parameter]
    public EventCallback<SearchResultSet> fetchedResultsChanged { get; set; }
    

    在搜索功能结束时,调用自定义事件:

    . . .
    fetchedResults = JsonConvert.DeserializeObject<SearchResultSet>(response);
    fetchedResultsChanged.InvokeAsync(fetchedResults);
    

    Index.razor

    <DefaultSearch @bind-fetchedResults=FetchedResults />
    
    @code {
         SearchResultSet FetchedResults {get; set;} // not a Parameter
    }
    

    评论:

    1. 要绑定变量,事件的名称必须与变量名+“已更改”完全一致
    2. 我发现 Visual Studio 经常给我一个错误,提示我无法将 EventCallback&lt;T&gt; 转换为 EventCallback。我相信这是一个智能感知错误。如果您遇到该特定错误,请尝试运行。

    【讨论】:

    • 我有Index.razor 做这项工作,因为DefaultSearch.razorSearchResultsPage.razor 都使用Index.razor 获得的数据,它们都是Index.razor 的组成部分。
    • DefaultSearch.razor不使用Index.razor获取的任何数据——Index.razor的声明中没有设置参数,也没有级联值。目前它所做的只是显示一个文本输入并将其绑定到一个字符串变量。如果您真的想在Index.razor 页面上完成所有搜索逻辑,那么DefaultSearch.razor 是什么意思?
    • 你是对的。我想用DefaultSearch.razor 搜索并在SearchResultsPage.razor 中显示结果。我只是想,因为他们都是Index.razor 的“孩子”,所以让Index.razor 完成所有工作并传递数据是有意义的。稍后我会在这里尝试您的建议。
    • 是的,如果您在其他框架中完成了大量的 Web 编程,那么习惯 Blazor 方式有时会感觉有点不对劲。但这是一般模式 - 将数据作为变量参数传递给组件,并通过 EventCallback 从它们传递。
    • 最后一个问题:你说“要绑定一个变量,事件必须完全命名为变量名+'Changed'”。这是 Blazor 中内置的东西(例如,我总是必须做的事情,否则它不会工作)还是只是为了您提供的示例?谢谢!
    【解决方案2】:

    希望以下内容有所帮助。注意添加到 DefaultSearch 参数的 OnClick 参数

    Index.razor 更改

    <DefaultSearch OnClick="SubmitSearch" />
    
    public void SubmitSearch(string action)
    {
        if (action == "PerformSearch")
        {
            //any required code
        }
    }
    

    DefaultSearch.razor 更改

    [Parameter]
    public EventCallback<string> OnClick { get; set; }
    
    public void DoSomething()
    {
        OnClick.InvokeAsync("PerformSearch");
    }
    

    【讨论】:

    • 我是否将 Index.razor 中的 try/catch 移动到新的 SubmitSearch() 方法?
    • @Brian 对不起,是的,这是正确的,并且可能不是传回“PerformSearch”,而是你会做 OnClick.InvokeAsync(queryString);
    猜你喜欢
    • 2020-05-19
    • 2022-12-22
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 1970-01-01
    相关资源
    最近更新 更多