Вызов метода в универсальном дочернем элементе управления Blazor - PullRequest
0 голосов
/ 28 июня 2019

Вызов метода в универсальном дочернем элементе управления

У меня есть контейнерный элемент управления с именем InfoPanel, который должен содержать экземпляры других элементов управления различных типов, но все они получены из базового класса с именем InfoPanelControl.InfoPanelControl определяет виртуальный метод Save.

Я хочу вызвать метод Save содержимого элемента управления из InfoPanel, чтобы каждый конкретный элемент управления выполнял свое собственное конкретное сохранение.

Вот как это выглядит:

<InfoPanel>
    <Budget />
</InfoPanel>

Здесь Budget получен из InfoPanelControl.

InfoPanel имеет свойство ChildControl:

[Parameter] private RenderFragment ChildContent { get; set; }

, которое заполняется экземплярами дочерних элементов управления, в данном примере это Budget.

Теперь мне нужно получить доступ к элементу управления Бюджет (как InfoPanelControl, потому что мне не нужен определенный тип, только базовый тип) из InfoPanel.В InfoPanel я надеялся сделать следующее:

InfoPanelControl childControl = ChildContent.Target as InfoPanelControl;

Однако то, что возвращает ChildContent.Target, не является Бюджетом, приведенным к InfoPanelControl.На самом деле это экземпляр элемента управления более высокого уровня, который является контейнером InfoPanel.

Как получить доступ к методам элемента управления Budget (приведенного к InfoPanelControl) из InfoPanel?

Ответы [ 2 ]

1 голос
/ 30 июня 2019

Как ни странно, я действительно сделал нечто подобное несколько дней назад. Я решил использовать каскадный параметр / значение для решения моей конкретной проблемы. Я использовал простой пример ниже, чтобы показать общую логику.

Я ожидаю, что в будущем будет лучшее решение для этого, но на момент написания Blazor все еще находится в предварительном просмотре.

Я также рекомендовал бы иметь ChildControlBase, который реализует интерфейс, от которого наследуются все дочерние элементы управления.

Дополнительной «хорошей вещью» в этой реализации является то, что она будет работать для нескольких дочерних компонентов, которые могут быть в «ChildContent», и разметка вокруг него не имеет значения.

В настоящее время я добавляю дочерний элемент к родительскому элементу в переопределении OnParametersSet. В зависимости от ваших потребностей вы можете использовать это по-другому или иметь дополнительную логику.

ParentControlBase.cs

    public class ParentControlBase : ComponentBase
{
    private List<IDoSomething> _childControls;

    public ParentControlBase()
    {
        _childControls = new List<IDoSomething>();
    }

    public void AddChildControl(IDoSomething control)
    {
        if (!_childControls.Contains(control))
        {
            _childControls.Add(control); 
        }
    }

    public void DoSomethingOnRelevantChildControls()
    {
        foreach (var control in _childControls)
        {
            control.DoSomething();
        }
    }
}

ParentControl.razor

@inherits ParentControlBase
<div class="parent-control-container">
<div>Parent Control</div>
    <CascadingValue Name="IDoSomethingParentControl" value="@this">
        @ChildContent
    </CascadingValue>
    <div class="btn btn-primary" @onclick="@DoSomethingOnRelevantChildControls">Do Something</div>
</div>
@code{
    [Parameter]
    private RenderFragment ChildContent { get; set; }
}

Реализация общего дочернего контроля

   public interface IDoSomething
    {
        void DoSomething();
    }

ChildControl

@implements IDoSomething
<div>ChildControl</div>

@code
{

    [CascadingParameter(Name = "IDoSomethingParentControl")]
    private ParentControlBase CurrentParentControl { get; set; }

    protected override void OnParametersSet()
    {
        if (CurrentParentControl != null)
        {
            CurrentParentControl.AddChildControl(this);
        }
    }

    public void DoSomething()
    {
        //Do Something implementation
    }

}
1 голос
/ 28 июня 2019

Свойство ChildContent.Target возвращает экземпляр сгенерированного класса , для которого текущий делегат RenderFragment вызывает метод экземпляра, который отображает содержимое.В этом случае, поскольку infoPanel определяет свойство ChildContent, ChildContent.Target возвращает контейнерный компонент infoPanel, а не Budget.ChildContent.Target устанавливается компилятором, и вы ничего не можете с этим поделать.На самом деле, мало что можно сделать в отношении делегата RenderFragment, и он обеспечивает очень маленький механизм обнаружения.

Ваша схема слишком сложна, по крайней мере на данный момент, для Blazor ... Я бы предложилвместо этого следующая реализация: Предоставить событие Save, созданное в вашем компоненте infoPanel и распространенное (уведомить) подписчикам (дочерним компонентам.).Это гораздо менее сложное решение, но я нахожу ваш вопрос очень интригующим и надеюсь, что оно решит то, что вы изначально хотели.Возможно, вам стоит попытать счастья в github ... очень часто Стив Андерсон решает такие проблемы.

Надеюсь, это поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...