输入文本值:恢复到以前的值

input text value: revert to previous value

我正在构建一个自定义 Blazor 组件,@inherits InputBase<string[]>

在内部解析输入 String[] 并将其转换为对象列表。

迭代该对象列表并为每个项目生成输入:

<input type="text" value="@_list[j].Value" @onchange="(e => UpdateItem(j, e))" />

UpdateItem 方法做几件事。例如,它更新集合中的项目并检查新值是否为空字符串,如果是则从集合中删除项目。

但是,当用户向输入文本添加无效字符时,UpdateItem 会将它们删除并执行 list[index] = v,但因为 list[index] == v 它不会更改基础项目或列表。 CurrentValue 保持正确,但界面不更新,例如输入文本保留无效值,这具有误导性。如果我删除该项目并将其插入同一索引,它仍然不起作用。删除和添加它确实更新了界面,但最后添加了项目,这令人困惑。

我尝试在 UpdateItem 方法和其他地方调用 StateHasChanged(),但没有帮助。

如何“告诉”输入值自行更新?或者我如何“标记”值已更新,尽管它是相同的以触发界面更新。

也许我对这个问题的处理方式完全错误。我从 <input @bind="@_list[j].Value"... /> 开始,效果很好,但我需要控制绑定以验证输入并最终更改它。这就是为什么我选择了描述的路线。

我认为有几个问题困扰着您。

首先这是一个工作演示页面,我认为它封装了您要实现的目标:

@page "/StringTester"
<h3>String Test Page</h3>

@foreach (var str in MyStrings)
{
    <div class="form">
        <input @key="str" class="form-control" value="@str.Value" @onchange="(e) => StringChanged(e, str.Key )" />
    </div>
}

@code {

    SortedList<int, string> MyStrings = new SortedList<int, string> { { 1, "UK" }, { 2, "Australia" }, { 3, "Spain" } };

    string[] invalidchars = { "=", "+" };

    //  Must be async and Task based for the Yield to work
    async Task StringChanged(ChangeEventArgs e, int key)
    {
        var val = e.Value.ToString();
        if (string.IsNullOrEmpty(val))
            MyStrings.Remove(key);
        else
        {
            var newvalue = InvalidCharStripper(val);
            if (MyStrings[key].Equals(newvalue))
            {
                MyStrings[key] = val;
                await Task.Yield();
            }
            MyStrings[key] = newvalue;
        }
    }

    //  quick and dirty method to do some input manipulation  - remove invalid chars from the string
    string InvalidCharStripper(string value)
    {
        foreach (var x in invalidchars)
        {
            value = value.Replace(x, string.Empty);
        }
        return value;
    }
}
  1. “字符串是对象,但按值传递”问题。

  2. Blazor 渲染器。当您创建输入时,它会呈现为 <input value="Australia">。当用户将其更改为“Austalia+”时,处理会删除“+”并将其设置为“Australia”。显示值“Austalia+”仅存在于实际浏览器DOM,而不存在于渲染器DOM。渲染器仍然认为它是“澳大利亚”,因此不会重新渲染它。

我已经通过将字符串数组设置为有序列表解决了第一个问题。它现在是一个对象并且有秩序。

我通过检查新值(删除了无效字符)是否与旧值相同来解决了第二个问题。如果是,那么我将 MyStrings 值设置为无效值,并将 Yield 控制返回给任务调度程序。事件处理程序现在在最终 MyStrings[key] = newvalue 代码块运行之前重新呈现组件。最后一次渲染组件,并为输入分配正确的值。

如果您想了解更多关于 Blazor 事件流程的信息,可以阅读更多内容 here