Blazor 重置绑定值

Blazor resets bind value

我无法理解 blazor 绑定。我创建了一个基本示例来说明我面临的问题:

假设我想创建一个组件来选择这样的日期和时间: ,具有 DateTime 类型的 Value 属性。

首先,我创建一个组件来保存时间输入:

@* TimeInput.razor *@
<input type="time" @onchange=Changed value=@Value.ToString("HH:mm") required>

@code {
    [Parameter] public DateTime Value { get; set; }

    [Parameter] public EventCallback<DateTime> ValueChanged { get; set; }

    public void Changed(ChangeEventArgs e)
    {
        Value = DateTime.Parse((string)e.Value!);
        ValueChanged.InvokeAsync(Value);
    }
}

然后我使用 select 输入和在上一步中创建的 TimeInput 组件创建一个组件:

@* DateTimeSelector.razor *@

<select @onchange=DateChanged>
    @for (int i = 0; i < 7; i++)
    {
        var date = new DateTime(2022, 1, 1).AddDays(i);
        <option value=@date.ToString("yyyy-MM-dd") 
                selected=@(Value.Date == date)>
            @date.ToString("dddd")
        </option>
    }
</select>
<TimeInput Value=Value ValueChanged=TimeChanged />

@code
{
    [Parameter] public EventCallback<DateTime> ValueChanged { get; set; }

    private void DateChanged(ChangeEventArgs arg)
        => Value = DateTime.Parse((string)arg.Value!).Add(Value.TimeOfDay);

    private void TimeChanged(DateTime time)
        => Value = Value.Date.Add(time.TimeOfDay);

    private DateTime value;

    [Parameter]
    public DateTime Value
    {
        get => value;
        set
        {
            Console.WriteLine($"Value is {value}"); // FOR DEBUGGING
            if (this.value != value)
            {
                this.value = value;
                ValueChanged.InvokeAsync();
            }
        }
    }
}

最后,我在一个页面中进行测试:

@page "/"

<p><DateTimeSelector @bind-Value=@dateTime /></p>
<p>Debug: <input type="text" value=@dateTime /></p>

@code {
    private DateTime dateTime = new DateTime(2022, 1, 3, 17, 0, 0);
}

加载页面时,组件按预期显示值 2022-01-03 17:00:

但是一旦用户更改值(例如,从下午 5 点到下午 6 点),该值就会重置为 0001-01-01 00:00:

如果我看一下控制台,我会看到:

那么为什么会这样呢?谁用默认日期为 属性 Value 调用(两次)setter?我该如何解决?

我有类似的问题,但没有找到合适的解决方案,所以我一直在寻找其他选择并发现了 Blazorise,它是一个组件库,其中包含 DateEdit 或 TimeEdit 等模块,可以解决您遇到的问题,它是替代方案,可能不是您所期望的,但使用起来非常简单!

<Field>
   <FieldLabel>Date</FieldLabel>
   <DateEdit TValue="DateTime?" Placeholder="Select Date" @bind-Date="@input.date"></DateEdit>
</Field>

嗯,只是一个小疏漏。在您的 DateTimeSelector 中,您必须使用值调用。

ValueChanged.InvokeAsync(); => ValueChanged.InvokeAsync(value);