Blazor получает вложенные компоненты с помощью Reflection - PullRequest
0 голосов
/ 25 февраля 2019

На самом деле я работаю над проверкой формы в проекте 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"/>

Я кодировал класс, который проверяет, что все компоненты InputValidation имеют свойство Valid в true .

@if (ViewModel.IsValid(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);
}

Это не работает, я знаю, но даже если мы используем Reflection (GetProperties, GetFields, GetMembers), он не будет возвращать ни одного члена InputValidation родительского компонента.

Мой вопрос: есть ли способ получить все дочерние компоненты с помощью Reflection?Если да, то как это сделать?

Я знаю, что Blazor все еще находится на ранней стадии, и я надеюсь, что он скоро выйдет, потому что это очень приятная технология!

Спасибо за ваши ответы!

1 Ответ

0 голосов
/ 25 февраля 2019

Здесь вам не нужно отражение (компонент InputValidation не является полем в родительском элементе, это компонент, который будет отображаться с помощью RenderTree).

Вы можете захватить ссылку на каждый компонент InputValidationиспользуя атрибут ref.

<InputValidation ref="@InputValidationRef" Id="@nameof(ViewModel.UrlInput)" Property="@ViewModel.UrlInput" On="@(x => string.IsNullOrEmpty(x))" Message="Url is empty" ActiveOnLoad="@false"/>

Обычно этот ref "InputValidationRef" будет полем, но вместо этого вы можете использовать свойство с пользовательским установщиком для создания списка (или любой другой коллекции, которая вам нравится)

List<InputValidation> InputValidations = new List<InputValidation>();
InputValidation InputValidationRef { set => InputValidations.Add(value); }

Таким образом, каждое InputValidation теперь будет записываться как ссылка, и для каждого будет установлено свойство InputValidationRef, которое, в свою очередь, будет хранить все ссылки в коллекции "InputValidations".

Теперь у вас есть коллекция, которую вы можете проверить по

InputValidations.All(iv => iv.Valid)

Примечание: коллекция заполняется только после визуализации компонента / страницы, поэтому при начальной загрузке страницы коллекция ссылок пуста дометод OnAfterRender / OnAfterRenderAsync вызывается.

...