Передача данных с двусторонним связыванием данных в Blazor

Вопрос или проблема

У меня есть компонент всплывающего окна, который оборачивает базовый компонент всплывающего окна, который оборачивает DxPopup (DevExpress). С двусторонним связыванием данных я ожидал, что значения свойств будут передаваться не только от родителя к ребенку, но и от ребенка к родителю. Правильно ли это ожидание? Вот мой код:

PopupBase.razor

@using DevExpress.Blazor

<DxPopup @bind-Visible="Visible">
</DxPopup>

@code {
    [Parameter]
    public bool Visible { get; set; }

    [Parameter]
    public EventCallback<bool> VisibleChanged { get; set; }

}

DetailPopup.razor

<PopupBase @bind-Visible="Visible">

</PopupBase>

@code {
    [Parameter]
    public bool Visible { get; set; }

    [Parameter]
    public EventCallback<bool> VisibleChanged { get; set; }
}

Page.razor

<DxButton Text="Показать всплывающее окно" Click="@ShowPopup" />

<DetailPopup @bind-Visible="showPopup" />

@code {
    bool showPopup = false;

    void ShowPopup()
    {
        showPopup = true;
    }
}

@bind-Visible должен включать двустороннее связывание и автоматически использовать события VisibleChanged для передачи значений параметров вверх к родителям, верно? Или нет? Должны ли параметры у родителей автоматически обновляться? Или мне нужно переключиться на @bind-Visible:get/set, чтобы добиться желаемого. Но даже с этим я читал, что нам не следует перезаписывать значения параметров, так что это также оставляет меня в недоумении.

Проблема в том, что если видимость не установлена правильно, то мы можем получить несколько всплывающих окон на экране (из разных компонентов).

Ответ или решение

Двусторонняя привязка данных в Blazor: Проблема с распространением данных в компоненте Popup

При разработке приложений на Blazor, важно правильно понимать механизмы двусторонней привязки данных, особенно когда мы имеем дело с компонентами, обрабатывающими состояние, такими как окна (попапы). Ваш код предоставляет интересный случай, в котором вы сталкиваетесь с вопросами о том, как параметры взаимодействуют друг с другом в системе компонентов.

Проблема с ожиданиями двусторонней привязки

Исходя из представленного вами кода, вы ожидаете, что при изменении свойства Visible в дочернем компоненте PopupBase, оно должно автоматически обновлять значение в родительском компоненте (DetailPopup), а затем и в конечном Page. Однако поведение, которое вы наблюдаете, может показаться неожиданным, если вы не совсем точно следуете правилам Blazor о том, как работает событие VisibleChanged.

Основная проблема

Когда вы используете директиву @bind-Visible, Blazor устанавливает связь, которая включает:

  1. Привязку значения свойства (Visible) из родителя в дочерний компонент.
  2. Событие VisibleChanged, которое должно срабатывать в дочернем компоненте, когда значение изменяется, чтобы обновить родителя.

Вы указали, что ваш компонент PopupBase не вызывает VisibleChanged, когда происходит изменение состояния Visible. Это, возможно, и является корнем проблемы.

Как исправить?

Для того чтобы двусторонняя привязка работала корректно, вам необходимо вручную вызывать VisibleChanged в PopupBase, когда значение видимости изменяется. Вот как можно сделать это:

  1. Измените свойство Visible в компоненте PopupBase так, чтобы оно использовало метод-сеттер.

  2. Вызывайте VisibleChanged.InvokeAsync(value) в сеттере при изменении видимости.

Вот переработанный код для PopupBase.razor:

@using DevExpress.Blazor

<DxPopup @bind-Visible="Visible">
</DxPopup>

@code {
    private bool visible;

    [Parameter]
    public bool Visible 
    { 
        get => visible; 
        set 
        {
            if (visible != value)
            {
                visible = value;
                VisibleChanged.InvokeAsync(value);
            }
        } 
    }

    [Parameter]
    public EventCallback<bool> VisibleChanged { get; set; }
}

Изменения в детализированном попапе

В DetailPopup.razor нет необходимости вносить изменения, если вы правильно передали параметры и события из PopupBase.

Резюме

Использование двусторонней привязки в Blazor требует четкого понимания того, как событие VisibleChanged должно быть вызвано, чтобы оно корректно обновляло родительские компоненты. Просто указание на @bind-Visible не гарантирует, что обновление будет происходить автоматически, если вы не реализуете вызов события в своем дочернем компоненте.

При применении этих изменений вы сможете избежать ситуаций с отображением нескольких попапов на экране, так как состояние будет корректно синхронизироваться во всей вашей иерархии компонентов.

Оцените материал
Добавить комментарий

Капча загружается...