在我的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访问器,我无法想象为什么。
答案 0 :(得分:0)
如果要强制UI重新呈现,请在Blazor 0.6中使用StateHasChanged()
get
{
return _display;
}
set
{
var parsed = Decimal.Parse(value);
_display = parsed.ToString("F2");
StateHasChanged();
}
Blazor不重新渲染的真正原因是:它试图保存重建的HTML。由于Blazor知道您将属性绑定到input
,因此它认为在设置属性后无需触发重新渲染。
更新工作:
onchange
事件已生成onchange
并致电amount.Display = "5";
答案 1 :(得分:0)
我相信您的问题与Blazor无关,与您的浏览器无关。
“ 1.00” =>“ 2”以“ 2.00”结尾。因为您的文本框的值已更改,因此您的浏览器引发了change事件。
“ 2.00” =>“ 2”保留为“ 2”,因为您的文本框的值未更改,因此您的浏览器不会引发change事件。
注意:触发事件后,将自动调用StateHasChanged方法。输入元素的数据绑定机制基于更改事件...同样,无需调用StateHasChanged方法。
答案 2 :(得分:0)
主要问题在于,如果Blazor认为其值未更改,则不会更新该文本框。您的示例的部分问题在于,值(您的属性)的内部表示有时与您在文本框中看到的内容(2
与2.00
)不吻合。但是就Blazor而言,如果属性值不变,就不会将绑定传播回文本框。
我试用了您的代码的多种变体(通常使用value
和onchange
“绑定”),但是最终如果您的代码完成了value属性的更新并且value是和以前一样,什么都不会发生。
我能想到的唯一解决方法是通过使用async引入一个非常丑陋的hack。执行此操作时,事件循环在await
之后完成(blazor将接受2
的新值),并且blazor将在恢复{{1}时再次检查是否有任何更改}调用,因为这是事件循环的新一轮。由于新值现在将是await
而不是2.00
,因此它将刷新文本框。
2
希望有人比我更了解Blazor,可以提供一些不那么残暴的东西。但这确实有效。 (顺便说一句,@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();
}
}
不能 起作用,大概是由于某些优化已使任务已经完成,因此并没有承诺退出事件循环。)
注意:
Blazor格式字符串(即Task.Delay(0)
)接受数字后,您可以通过将值存储为十进制并直接在razor标记中使用格式字符串来简化此操作。