Blazor 通过反射获取嵌套组件
Blazor get nested components by Reflection
我实际上正在 Blazor 项目 (0.8.0) 中进行表单验证。
我创建了一个名为 InputValidation 的组件。该组件接收许多参数来根据我们可以设置的条件测试 属性 值是否正确。
@using System.Linq.Expressions;
@typeparam TItem
@if (!Valid)
{
<span id="@(Id)_validation" class="form-text text-danger">@Message</span>
}
@functions {
[Parameter]
string Id { get; set; }
[Parameter]
TItem Property { get; set; }
[Parameter]
Expression<Func<TItem, bool>> On { get; set; }
[Parameter]
string Message { get; set; }
[Parameter]
bool ActiveOnLoad { get; set; } = true;
internal bool Valid { get; set; }
bool Activated;
protected async override Task OnInitAsync()
{
Activated = ActiveOnLoad;
}
protected async override Task OnAfterRenderAsync()
{
Activated = true;
}
protected async override Task OnParametersSetAsync()
{
Valid = !On.Compile().Invoke(Property);
}
}
您可以像这样在您的父组件上实现它:
<InputValidation Id="@nameof(ViewModel.UrlInput)" Property="@ViewModel.UrlInput" On="@(x => string.IsNullOrEmpty(x))" Message="Url is empty" ActiveOnLoad="@false"/>
我编写了一个 class 代码来验证所有 InputValidation 组件在 true 时都具有 属性 有效。
@if (ViewModel.IsValid(this))
this代表父组件
问题是……它不工作!
验证器代码如下:
public static class ModelValidator
{
public static bool IsValid<T, V>(this T viewmodel, V component) where T : IViewModel where V : ComponentBase
=> component.GetType().GetFields().OfType<InputValidation<T>>().All(x => x.Valid);
}
它不起作用,我知道,但即使我们使用反射(GetProperties、GetFields、GetMembers),它也不会 return 父组件的任何 InputValidation 成员。
我的问题是:有没有办法通过反射获取所有子组件?如果是,怎么做?
我知道 Blazor 仍处于早期阶段,我希望它能尽快发布,因为它是一项非常令人愉快的技术!
感谢您的回复!
这里不需要反射(InputValidation组件不是parent中的字段,它是一个会被RenderTree渲染的组件)。
您可以使用 ref 属性捕获对每个 InputValidation 组件的引用。
<InputValidation ref="@InputValidationRef" Id="@nameof(ViewModel.UrlInput)" Property="@ViewModel.UrlInput" On="@(x => string.IsNullOrEmpty(x))" Message="Url is empty" ActiveOnLoad="@false"/>
通常此 ref "InputValidationRef" 将是一个字段,但您可以使用带有自定义 setter 的 属性 来构建列表(或您喜欢的任何集合)
List<InputValidation> InputValidations = new List<InputValidation>();
InputValidation InputValidationRef { set => InputValidations.Add(value); }
因此,每个 InputValidation 现在都将被捕获为一个引用,并且将为每个 InputValidation 设置 属性 InputValidationRef,这将依次将所有引用存储在集合 "InputValidations" 中。
现在,你有了一个集合,你可以针对
进行测试
InputValidations.All(iv => iv.Valid)
注意:该集合仅在 component/page 呈现后填充,因此在初始页面加载期间,引用集合为空,直到调用 OnAfterRender/OnAfterRenderAsync 方法。
我实际上正在 Blazor 项目 (0.8.0) 中进行表单验证。
我创建了一个名为 InputValidation 的组件。该组件接收许多参数来根据我们可以设置的条件测试 属性 值是否正确。
@using System.Linq.Expressions;
@typeparam TItem
@if (!Valid)
{
<span id="@(Id)_validation" class="form-text text-danger">@Message</span>
}
@functions {
[Parameter]
string Id { get; set; }
[Parameter]
TItem Property { get; set; }
[Parameter]
Expression<Func<TItem, bool>> On { get; set; }
[Parameter]
string Message { get; set; }
[Parameter]
bool ActiveOnLoad { get; set; } = true;
internal bool Valid { get; set; }
bool Activated;
protected async override Task OnInitAsync()
{
Activated = ActiveOnLoad;
}
protected async override Task OnAfterRenderAsync()
{
Activated = true;
}
protected async override Task OnParametersSetAsync()
{
Valid = !On.Compile().Invoke(Property);
}
}
您可以像这样在您的父组件上实现它:
<InputValidation Id="@nameof(ViewModel.UrlInput)" Property="@ViewModel.UrlInput" On="@(x => string.IsNullOrEmpty(x))" Message="Url is empty" ActiveOnLoad="@false"/>
我编写了一个 class 代码来验证所有 InputValidation 组件在 true 时都具有 属性 有效。
@if (ViewModel.IsValid(this))
this代表父组件
问题是……它不工作!
验证器代码如下:
public static class ModelValidator
{
public static bool IsValid<T, V>(this T viewmodel, V component) where T : IViewModel where V : ComponentBase
=> component.GetType().GetFields().OfType<InputValidation<T>>().All(x => x.Valid);
}
它不起作用,我知道,但即使我们使用反射(GetProperties、GetFields、GetMembers),它也不会 return 父组件的任何 InputValidation 成员。
我的问题是:有没有办法通过反射获取所有子组件?如果是,怎么做?
我知道 Blazor 仍处于早期阶段,我希望它能尽快发布,因为它是一项非常令人愉快的技术!
感谢您的回复!
这里不需要反射(InputValidation组件不是parent中的字段,它是一个会被RenderTree渲染的组件)。
您可以使用 ref 属性捕获对每个 InputValidation 组件的引用。
<InputValidation ref="@InputValidationRef" Id="@nameof(ViewModel.UrlInput)" Property="@ViewModel.UrlInput" On="@(x => string.IsNullOrEmpty(x))" Message="Url is empty" ActiveOnLoad="@false"/>
通常此 ref "InputValidationRef" 将是一个字段,但您可以使用带有自定义 setter 的 属性 来构建列表(或您喜欢的任何集合)
List<InputValidation> InputValidations = new List<InputValidation>();
InputValidation InputValidationRef { set => InputValidations.Add(value); }
因此,每个 InputValidation 现在都将被捕获为一个引用,并且将为每个 InputValidation 设置 属性 InputValidationRef,这将依次将所有引用存储在集合 "InputValidations" 中。
现在,你有了一个集合,你可以针对
进行测试InputValidations.All(iv => iv.Valid)
注意:该集合仅在 component/page 呈现后填充,因此在初始页面加载期间,引用集合为空,直到调用 OnAfterRender/OnAfterRenderAsync 方法。