【问题标题】:How to pass value from Child component (RenderFragment) to Parent page in C# Blazor?如何将值从子组件(RenderFragment)传递到 C# Blazor 中的父页面?
【发布时间】:2021-05-22 05:13:51
【问题描述】:

我有一个 Blazor 项目,它加载包含 razor 组件的 DLL。为了在客户端渲染这些动态组件,我使用渲染树构建器从动态组件创建一个RenderFragment 并将其放置在页面上以显示该组件。但是,我在创建渲染树时找不到绑定值的方法。通常情况下,我可以使用下面的父子组件示例传递数据,但是在将动态组件转换为RenderFragment时不知道该怎么做。

父组件

@page "/ParentComponent"

<h1>Parent Component</h1>

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

@code {
    private string _password;
 }

子组件

<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;
    }
}

动态组件到RenderFragment

下面的代码显示了我如何通过将组件转换为RenderFragment 在页面上显示组件。你知道我如何在渲染树构建器中绑定一个变量,以将数据从动态组件传递到父页面吗?

注意:这个动态组件@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();
    };
}

【问题讨论】:

    标签: c# asp.net razor blazor


    【解决方案1】:

    让我们先看看我是否理解你的意思......你想创建一种组件渲染器,它获取组件的名称作为参数,并通过 IComponentService 获取组件的Type,然后渲染它。我也猜想组件的Type可能是Type Child,你想知道如何在Index页面渲染它,并获取在Child组件中输入的密码,对吧? 下面的代码描述了如何做到这一点,但是我当然不能使用 IComponentService 服务来发现组件的类型,而是假设类型是Child

    复制并运行代码sn-p。测试一下...它应该可以工作...

    @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();
    
        };
    }
    

    注意:您不应修改子组件中参数属性的值。 Blazor 中的参数属性是自动属性,这意味着您可以访问它们的值,但不能更改它们。

    另外,您不应该通过循环创建序列号。序列号应该是硬编码的。谷歌搜索 Steve Anderson 的一篇文章中讨论的这个主题。

    【讨论】:

    • 嗨@enet。你的解决方案奏效了。谢谢你。另外,如果我想绑定一个类,例如PluginData,它有一个名为_password 的字符串属性,我该如何修改上面的解决方案来实现呢?
    • 对不起,我不确定我是否理解你,除非你详细解释你的要求。但是,您可以将参数传递给您可以在代码中使用的 dynamicComponent 方法。您还可以在 dynamicComponent 方法之外定义属性并从方法中访问它们
    • 我的意思不是将字符串数据从子组件传递到页面组件,是否可以将具有多个属性(例如用户名、密码等)的对象从子组件传递到父组件?跨度>
    • 我之前正在研究它,我将字符串属性切换为具有多个属性的类。它应该可以工作,但这并不是我寻求您帮助的原因。我刚才又试了一次,发现自己犯了一个小错误。现在它起作用了。这样我可以绑定更多的数据。谢谢@enet。
    • 是的,你可以传递一个对象或对象的集合...
    猜你喜欢
    • 2021-05-02
    • 2021-09-11
    • 2022-11-23
    • 2021-01-29
    • 1970-01-01
    • 2021-03-19
    • 2020-06-18
    • 2020-05-25
    • 2021-01-20
    相关资源
    最近更新 更多