简体   繁体   English

如何将值从子组件(RenderFragment)传递到 C# Blazor 中的父页面?

[英]How to pass value from Child component (RenderFragment) to Parent page in C# Blazor?

I have a Blazor project that loads DLL that contain razor components.我有一个 Blazor 项目,它加载包含 razor 组件的 DLL 项目。 To render these dynamic components at client-side, I use render tree builder to create a RenderFragment from dynamic component and place it on the page to show the component.为了在客户端渲染这些动态组件,我使用渲染树构建器从动态组件创建一个RenderFragment并将其放置在页面上以显示该组件。 However, I can't find a way to bind a value while creating the render tree.但是,我在创建渲染树时找不到绑定值的方法。 Normally, I can pass data using the example below of parent and child component, but not sure how to do it when converting dynamic components to RenderFragment .通常,我可以使用下面的父子组件示例传递数据,但不确定在将动态组件转换为RenderFragment时如何做。

Parent component父组件

@page "/ParentComponent"

<h1>Parent Component</h1>

<ChildComponent @bind-Password="_password" />

@code {
    private string _password;
 }

Child component子组件

<h1>Child Component</h1>

Password:

<input @oninput="OnPasswordChanged"
       required
       type="@(_showPassword ? "text" : "password")"
       value="@Password" />

<button class="btn btn-primary" @onclick="ToggleShowPassword">
    Show password
</button>

@code {
    private bool _showPassword;

    [Parameter]
    public string Password { get; set; }

    [Parameter]
    public EventCallback<string> PasswordChanged { get; set; }

    private Task OnPasswordChanged(ChangeEventArgs e)
    {
        Password = e.Value.ToString();
        return PasswordChanged.InvokeAsync(Password);
    }
    private void ToggleShowPassword()
    {
        _showPassword = !_showPassword;
    }
}

Dynamic Component to RenderFragment RenderFragment的动态组件

The code below shows how I am able to show the component on the page by converting it to RenderFragment .下面的代码显示了我如何通过将组件转换为RenderFragment在页面上显示该组件。 Do you know how I can bind a variable at the render tree builder, to pass data from dynamic component to the parent page?您知道如何在渲染树构建器中绑定变量,以将数据从动态组件传递到父页面吗?

Note: This Dynamic Component @dynamicComponent is same as the Child component above and I want the password data from it.注意:这个动态组件@dynamicComponent与上面的子组件相同,我想要从中获取密码数据。

@page "/{ComponentName}"
@inject IComponentService ComponentService

@if (render)
{
    @dynamicComponent()
    
    @_password;
}
    
@code{
    private string _password;
    
    [Parameter]
    public string ComponentName { get; set; }
    bool render = false;
    
    protected override void OnInitialized()
    {
        render = true;
        base.OnInitialized();
    }
    
    RenderFragment dynamicComponent() => builder =>
    {
        RazorComponentModel component = ComponentService.GetComponentByPage(ComponentName);
        builder.OpenComponent(0, component.Component);
        for (int i = 0; i < component.Parameters.Count; i++)
        {
            var attribute = component.Parameters.ElementAt(i);
            builder.AddAttribute(i + 1, attribute.Key, attribute.Value);
        }
        builder.CloseComponent();
    };
}

Let us first see if I understood you right... You want to create a sort of component renderer, which gets a component's name as a parameter, and by means of the IComponentService you gets the component's Type , and then render it.让我们先看看我的理解是否正确......您想创建一种组件渲染器,它获取组件的名称作为参数,并通过 IComponentService 获取组件的Type ,然后渲染它。 I also guess that the component's Type may be Type Child , and you want to know how to render it in the Index page, and gets the password entered in the Child component, right?我也猜想组件的Type可能是Type Child ,你想知道如何在 Index 页面中渲染它,并获取在 Child 组件中输入的密码,对吧? The following code describes how to do that, but of course I cannot use the IComponentService service to discover the type of the component, but instead assume that the type is Child .下面的代码描述了如何做到这一点,但是我当然不能使用 IComponentService 服务来发现组件的类型,而是假设类型是Child

Copy and run the code snippet.复制并运行代码片段。 Test it... It should work...测试它......它应该工作......

@page "/{ComponentName?}"

@using Microsoft.AspNetCore.Components.CompilerServices;

@if (render)
{
    @dynamicComponent
   
}

<p>Your password: @_password</p>
@code{
    private string _password;

    [Parameter]
    public string ComponentName { get; set; }

    bool render = false;

    protected override void OnInitialized()
    {
        render = true;
        base.OnInitialized();
    }

    RenderFragment dynamicComponent => builder =>
    {
        builder.OpenComponent(0, typeof(Child));
        builder.AddAttribute(1, "Password", _password);
        builder.AddAttribute(2, "PasswordChanged", 
            EventCallback.Factory.Create<string>(this, 
            RuntimeHelpers.CreateInferredEventCallback(this, __value => _password = __value, _password)));
        builder.CloseComponent();

    };
}

Note: You should not modify the values of the parameter properties in your Child component.注意:您不应修改子组件中参数属性的值。 Parameter properties in Blazor are auto properties, meaning that you can access their values but you must not change them. Blazor 中的参数属性是自动属性,这意味着您可以访问它们的值但不能更改它们。

Also, you shouldn't create sequence number by a loop.此外,您不应该通过循环创建序列号。 Sequence numbers should be hard-coded.序列号应该是硬编码的。 Googlize this subject discussed in an article by Steve Anderson.谷歌搜索 Steve Anderson 的一篇文章中讨论的这个主题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM