Связанное свойство не обновляется при изменении - PullRequest
0 голосов
/ 20 октября 2018

В моем приложении Blazor у меня есть следующее поле ввода в виде:

<input bind="@amount.Display" type="text" />

Это связано со свойством, определенным со следующими средствами доступа:

get
{
    return _display;
}
set
{
    var parsed = Decimal.Parse(value);
    _display = parsed.ToString("F2");
}

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

Обычно, когда пользователь вводит «2», затем вкладки или щелчки из поля ввода, я бы хотел, чтобы это автоматически конвертировалось в «2,00».Странно то, что это преобразование происходит только в том случае, если пользователь вводит строку, представляющую число, отличное от уже существующего.Например, если поле ввода в настоящее время имеет значение «1,00», и я ввожу «2», я правильно получаю «2,00».Но если поле ввода имеет значение «2,00» и я ввожу «2», оно просто остается «2».Как будто в этом последнем случае не вызывается метод доступа set, и я не могу себе представить, почему.

Ответы [ 3 ]

0 голосов
/ 20 октября 2018

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

"1.00" => "2" заканчивается "2.00".потому что значение вашего текстового поля изменилось, и, следовательно, ваш браузер вызовет событие изменения.

"2.00" => "2" остается "2", потому что значение вашего текстового поля не изменилось, и, таким образом,Ваш браузер не вызывает событие изменения.

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

0 голосов
/ 21 октября 2018

Основная проблема в том, что Blazor просто не собирается обновлять текстовое поле, если считает, что его значение не изменилось.Частично эта проблема в вашем примере заключается в том, что внутреннее представление значения (вашего свойства) иногда не соответствует тому, что вы видите в текстовом поле (2 против 2.00).Но что касается Blazor, если значение свойства не меняется, оно не будет распространять привязку обратно в текстовое поле.

Я поиграл с несколькими вариантами вашего кода (ручная «привязка» с использованиемvalue и onchange) но, в конечном счете, если к тому времени, когда ваш код завершит обновление свойства value, и значение будет таким же, как было раньше, ничего не произойдет.

Единственный обходной путь, который я могу придуматьэто ввести действительно уродливый взлом с помощью асинхронного.Когда вы это сделаете, цикл обработки событий завершается после await (Blazor примет новое значение 2), и Blazor снова проверит, изменилось ли что-нибудь, когда он возобновит вызов await с того моментаэто новый раунд цикла событий.Поскольку новое значение теперь будет 2.00 вместо 2, оно обновит текстовое поле.

@functions {
    private string value;

    private string Value
    {
        get => value;
        set => SetValue(value);
    }

    private async void SetValue(string value)
    {
        this.value = value;
        await Task.Delay(1);
        this.value = decimal.Parse(value).ToString("F2");
        StateHasChanged();
    }
}

Надеюсь, кто-то, кто знает больше о Блазоре, чем я, может предложить что-то менее зверское.Но это работает .(Кстати, Task.Delay(0) не работает , а не , вероятно, из-за некоторой оптимизации, когда задача уже выполнена и поэтому не предполагает обещания выйти из цикла событий.)

Примечание:
Как только строки формата Blazor (то есть format-value="yyyy-MM-dd") принимают числа, вы, вероятно, сможете упростить это, просто сохранив значение в виде десятичной дроби и напрямую используя строку формата в разметке бритвы.

0 голосов
/ 20 октября 2018

Если вы хотите принудительно выполнить рендеринг пользовательского интерфейса, в Blazor 0.6 я рекомендую использовать StateHasChanged()

get
{
    return _display;
}
set
{
    var parsed = Decimal.Parse(value);
    _display = parsed.ToString("F2");
    StateHasChanged();
}

Истинная причина, по которой Blazor не выполняет рендеринг: это попыткасохранить восстановление HTML.Поскольку Blazor знает, что вы связали свойство с input, он считает, что нет необходимости запускать повторный рендеринг после установки свойства.

Работа по обновлению:

  1. Пользователь вводит текст '5' и нажимает Tab
  2. Html onchange событие сгенерировано
  3. Захват Blazor onchange чёт и звони amount.Display = "5";
  4. Готово.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...