如何将值从子组件 (RenderFragment) 传递到 C# Blazor 中的父页面?
How to pass value from Child component (RenderFragment) to Parent page in C# Blazor?
我有一个 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();
};
}
让我们先看看我的理解是否正确...您想创建一种组件渲染器,它获取组件的名称作为参数,并通过 IComponentService 获取组件的 Type
,然后渲染它。我也猜测组件的Type
可能是Type Child
,你想知道如何在Index页面渲染它,并获取在Child组件中输入的密码,对吧?
下面的代码描述了如何做到这一点,但是我当然不能使用 IComponentService 服务来发现组件的类型,而是假设类型是 Child
.
复制并运行 代码片段。测试它...它应该工作...
@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) 的一篇文章中讨论的这个主题。
我有一个 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();
};
}
让我们先看看我的理解是否正确...您想创建一种组件渲染器,它获取组件的名称作为参数,并通过 IComponentService 获取组件的 Type
,然后渲染它。我也猜测组件的Type
可能是Type Child
,你想知道如何在Index页面渲染它,并获取在Child组件中输入的密码,对吧?
下面的代码描述了如何做到这一点,但是我当然不能使用 IComponentService 服务来发现组件的类型,而是假设类型是 Child
.
复制并运行 代码片段。测试它...它应该工作...
@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) 的一篇文章中讨论的这个主题。