Как установить значение частного поля или свойства в компоненте в зависимости от значения параметра

Мой код:

Родитель:

<ChildComponent UserName = "@userName"/>

Дочерний компонент:

<button disabled = "@disableForwardToUser">OK</button>

@code {
[Parameter]
public string UserName { get; set; }

private bool disableForwardToUser = false;
}

Теперь я хотел бы, чтобы приватный файл disableForwardToUser устанавливался в зависимости от значения UserName при загрузке компонента, примерно так:

if (string.IsNullOrEmpty(UserName))
{
    disableForwardToUser = true;
}

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

Для развертывания Сайтов с использованием Blazor, Angular и React с репозиторием на GitHub на Cloudflare.
Для развертывания Сайтов с использованием Blazor, Angular и React с репозиторием на GitHub на Cloudflare.
Как развернуть сайты с помощью Blazor, Angular и React с репозиторием на GitHub на Cloudflare.
0
0
54
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете сделать это с помощью метода OnInitialize дочернего компонента следующим образом:

 <h3>ChildComponent</h3>
    <button disabled = "@disableForwardToUser">OK</button>
    @disableForwardToUser
    
    @code {
        [Parameter]
        public string UserName { get; set; }
    
        private bool disableForwardToUser = false;
    
        protected override void OnInitialized()
        {
            base.OnInitialized();
            if (string.IsNullOrEmpty(UserName))
            {
                disableForwardToUser = true;
            }
        }
    
    }

OnParametersSet() лучше, так как вы хотите, чтобы параметры были установлены первыми.
Robert Harvey 22.02.2023 12:23

Вы правы, Однако Оскар сказал, что: when the component is loaded

AlirezaK 22.02.2023 12:26

[Вежливый] Совершенно правильный ответ (с использованием OnParametersSet), но вам не нужно использовать какие-либо методы жизненного цикла. Компонент отображается каждый раз, когда UserName обновляется, поэтому disableForwardToUser может быть простым геттером. Смотрите мой ответ ниже.

MrC aka Shaun Curtis 22.02.2023 12:37

Интересно, что можно и так сделать, спасибо!

Oskar 22.02.2023 13:03
Ответ принят как подходящий

Вам не нужно использовать какие-либо события, просто простой геттер.

<button class = "btn btn-success" disabled = "@_disableForwardToUser">OK</button>

@code {
    [Parameter] public string? UserName { get; set; }

    private bool _disableForwardToUser => string.IsNullOrWhiteSpace(this.UserName);
}

Компонент отображается каждый раз при изменении UserName.

Вот моя тестовая страница:

@page "/"

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<div class = "m-2 p-2">
    <ChildComponent UserName = "@_userName" />
</div>

<div class = "m-2 p-2">
    <button class = "btn btn-primary" @onclick=this.UpdateName>Change User</button>
</div>

@code {
    private string? _userName;

    private void UpdateName()
        => _userName = _userName is null ? "Fred" : null;
}

Сработало отлично, спасибо! Однако теперь disableForwardToUser доступен только для чтения, как мне дать ему «сеттер»? Я пытался сделать это так, но это не сработало: private bool disableForwardToUser { get => string.IsNullOrWhiteSpace(this.UserName); set; }

Oskar 22.02.2023 15:05

Зачем тебе сеттер? Как вы его установите? Это условно на основе значения this.UserName.

MrC aka Shaun Curtis 22.02.2023 15:24

На самом деле мне это не нужно в этом конкретном случае, но я использую тот же код в другом случае, где мне также нужно установить значение поля в функции в компоненте. Как мне совместить лямбда-выражение на get с «нормальным» автоустановщиком set;, чтобы поле не было только готовым?

Oskar 22.02.2023 16:01

Добавьте еще одно поле, которое устанавливает ваш процесс, а затем выполните AND или OR в disableForwardToUser, чтобы получить правильный логический ответ.

MrC aka Shaun Curtis 22.02.2023 17:41

Или, если это не сработает, опубликуйте здесь еще один вопрос с минимальным воспроизводимым примером.

MrC aka Shaun Curtis 22.02.2023 17:42

Я создал отдельный вопрос с примером кода stackoverflow.com/questions/75542495/…

Oskar 23.02.2023 09:57

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

    private string? username;
    [Parameter]
    public string? Username {
        get => username; set {
            username = value;
            disableForwardToUser = string.IsNullOrWhiteSpace(username);
        }
    }

[Вежливо] Это не лучший способ сделать это. Вы должны объявлять параметры только со стандартным {get; set;}. Их ни в коем случае нельзя модифицировать, а зависание процессов от них затянет процесс настройки. В этом случае вы делаете что-то довольно простое, но как только вы перейдете эту границу, другие будут думать, что это нормально делать что угодно.

MrC aka Shaun Curtis 22.02.2023 14:17

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

Roberto Ferraris 22.02.2023 15:30

Прошу вежливо не согласиться. Давайте посмотрим на ваш пример. Вы связываете параметр с внутренним полем. Теперь допустим, что внутренний процесс в OnParametersSet устанавливает userName другое значение. Теперь у вас есть несоответствие между тем, что визуализатор считает значением, и тем, что оно есть на самом деле. Это может вызвать проблемы с различиями и рассинхронизацию пользовательского интерфейса с RenderTree.

MrC aka Shaun Curtis 22.02.2023 17:34

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

MrC aka Shaun Curtis 22.02.2023 17:34

В моем коде [Параметр] связан с общедоступным свойством Username, а не с закрытым резервным полем username. Таким образом, теоретически никто не может получить доступ к резервному полю из внешнего кода (кроме случаев, когда используется Reflection). В любом случае, я понимаю ваши комментарии и опасения. Поскольку я не нашел исходного кода, чтобы увидеть, как работает ParameterAttribute под крючком, я согласен, что лучше избегать моего решения. Я буду продолжать расследование, у вас есть какие-то документы? Спасибо

Roberto Ferraris 22.02.2023 18:11

Другие вопросы по теме