Har*_*rry 2 c# .net-core blazor
我有一个剃须刀组件。该组件有一个参数,EventCallback
准确地说,名为“ValueChanged”。
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
Run Code Online (Sandbox Code Playgroud)
我在一个剃刀文件中准确地提到了这个事件,如下所示:
<Autocomplete DataSource="@Data" Columns="Id,Name" ValueChanged="OnUnitBrandIdChanged" />
Run Code Online (Sandbox Code Playgroud)
我将属性名称重命名(通过 F2,AKA 重构)为“OnValueChanged”。razor 文件没有自动更新(我猜是 Visual Studio 中的一个错误)。所以我手动更新了它。所以现在两个兴趣点看起来像这样:
[Parameter]
public EventCallback<string> OnValueChanged { get; set; }
Run Code Online (Sandbox Code Playgroud)
和
<Autocomplete DataSource="@Data" Columns="Id,Name" OnValueChanged="OnUnitBrandIdChanged" />
Run Code Online (Sandbox Code Playgroud)
代码编译并运行,然后运行时崩溃并显示以下错误消息
未处理的异常呈现组件:“Woof.Blazor.Components.Autocomplete”类型的对象没有与名称“ValueChanged”匹配的属性。
我浪费了 4 个小时调查这个案子。首先,我将名称“OnValueChanged”更改为“SomethingElse”——以确保我的源代码中根本不存在字符串“ValueChanged”。当然,我收到相同的错误消息。
然后我搜索了项目中的所有文件,包括字符串“ValueChanged”的隐藏文件和二进制文件。当然,我在obj
,bin
和.vs
目录中找到了字符串。所以我删除了那些文件。
再次编译代码后,我收到相同的错误消息。带有“ValueChanged”参考的那个。
我创建了全新的 Blazor 项目。我复制了我所有的代码文件,三重检查它们都没有包含“ValueChanged”字符串。
当新项目运行时 - 我收到相同的错误消息。
我想也许 Visual Studio 已经在隐藏位置的项目目录外的文件中写入了引用。所以我从项目中删除了所有临时文件,将其发布在 GitHub 上并发送给我的同事。他克隆了该项目,运行它并收到相同的错误消息。
我创建了名为“ValueChanged”的属性,虚拟属性,object
类型。完全未使用和冗余。当然程序运行没有错误。
似乎对该名称的引用隐藏在某处,但我不知道在哪里。没有 Windows 工具能够在项目目录中搜索“ValueChanged”字符串。我什至怀疑 Visual Studio 可以通过加密和/或压缩内容来隐藏引用,但我再次三重检查我删除了所有二进制文件,所有非纯文本文件。
一无所有。
然后我创建了全新的 Blazor 项目。创建了一个测试组件,创建了一个事件,绑定了虚拟事件处理程序,编译并运行。一切正常。然后我以与原始程序完全相同的方式重构了我的测试程序。它有效,完全没有问题。我什至使用了完全相同的名称、类型、目录结构、命名空间,我什至添加了名为“Value”的参数,以使我的测试用例更类似于生产代码。结果是新项目正常运行。我可以重命名任何参数,它就可以工作。
我的旧项目即使几乎从头开始重写而没有在任何文件中出现字符串“ValueChanged”,也不会正常运行。同样的错误信息。与 Visual Studio 和 Blazor 一样,通用逻辑不再适用。这个名字不存在,但是当我编译代码时,它突然出现在带有g.cs
扩展名的临时文件中。
这很可能是 Visual Studio / .NET Core 中的一个可怕的错误,但要报告它我应该能够重现它,但在这种情况下 - 我不能。有什么线索吗?
顺便说一句,当然我尝试调试它并在被诅咒的属性设置器上设置断点。它被触发,但是我的调用堆栈中唯一的项目是“外部代码”,所以它完全没用。
请注意以下事项:
如果该组件是绑定到父组件的子组件,则通常在组件中定义参数属性,在这种情况下,父组件绑定到应在子组件中定义的 Value 属性,并使用 Parameter 修饰属性也一样。因此,您的子组件应如下所示
private string _value;
[Parameter]
public string Value
{
get { return _value ?? string.Empty; }
set
{
if (Value != value)
{
_value = value;
}
}
}
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
Run Code Online (Sandbox Code Playgroud)
下面是组件在父组件中的用法
<ChildComponent @bind-Value="value" />
@code
{
private string value;
}
Run Code Online (Sandbox Code Playgroud)
注意:上面的代码(ParentComponent)嵌入了之前定义的子组件,并将名为value的局部变量绑定到子组件的Value属性上。当您想Component
从父组件绑定到 a 的属性时,您可以使用 @bind 指令 + 连字符 + 属性名称,例如:@bind-Password="password"。在有界组件(子组件)中,您应该定义属性(在最后一个实例中它应该是 Password)和一个委托参数属性(在最后一个实例中它应该是
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
Run Code Online (Sandbox Code Playgroud)
) 如您所见,我们必须拥有这一对。但是 ValueChanged 或 PasswordChanged 是编译器用来在幕后生成代码的构造,这些代码支持父组件和子组件之间的通信。更准确地说,编译器生成的代码支持组件之间的双向数据绑定……您不能使用 ValueChanged 或 PasswordChanged 作为事件处理程序的属性。你唯一能做的就是触发代表。因此,您可以element
在子组件中放置一个输入,并将输入元素的 value 属性绑定到组件的 Value 属性,如下所示:
<input type="text" value="@Value" @oninput="OnValueChanged" />
Run Code Online (Sandbox Code Playgroud)
这是一个单向从结合值的子组件的的属性值的元素的属性。我们还必须更新 Value 属性,在这种情况下,每当用户键入字符时...为此我们需要定义一个事件处理程序,在每次敲击键盘后调用,如下所示:
private Task OnValueChanged(ChangeEventArgs e)
{
Value= e.Value.ToString();
return ValueChanged.InvokeAsync(Value);
}
Run Code Online (Sandbox Code Playgroud)
如您所见,OnValueChanged 方法将输入到文本框中的值(在每次敲击键盘时完成)分配给 Value 属性,然后...... ..... 触发ValueChanged委托,将 Value 属性的值传递给它。这是你应该用ValueChanged做的事情,没有别的。现在,当委托被触发时,父组件中私有值字段的值会更新为子组件的 Value 属性的值。这个过程称为组件间数据绑定的两种方式
归档时间: |
|
查看次数: |
1677 次 |
最近记录: |