使用 Blazor 将输入文本动态绑定到类/对象属性
Posted
技术标签:
【中文标题】使用 Blazor 将输入文本动态绑定到类/对象属性【英文标题】:Dynamically binding input-text to class/object propertys using Blazor 【发布时间】:2020-06-04 23:15:24 【问题描述】:我正在尝试使用 Blazor 为类中的属性构建输入字段的动态列表,但无法弄清楚如何将输入框的内容绑定/链接到类的属性。 (该类可以有大量的公共属性,不仅仅是下面例子中的名称和描述,它们并不总是“字符串”类型)
假设我有这个类/模型:
public class customer
public string Name get; set;
public int Age get; set;
public string Description get; set;
我得到了这个 blazor 组件(updateC.razor):
@inherits CLogic
@if (nfo != null)
@foreach (var obj in nfo)
<input type="text" class="form-control"
bind=@SCustomer.GetType().GetProperty(obj.ToString())/>
最后是 Clogic:
public class Clogic: ComponentBase
[Parameter]
public Customer SCustomer get; set; = new Customer();
[Parameter]
public PropertyInfo[] nfo get; set;
protected override void OnAfterRender(bool firstRender)
if (firstRender)
nfo = SCustomer.GetType().GetProperties();
StateHasChanged();
这是假设将每个输入字段中所做的更改绑定到当前 SCustomer 实例中的正确属性(输入时,假设更新类/对象的正确属性) .这不起作用,SCustomer 内部的值在输入完成后不会更改。我猜我完全错了,但似乎无法弄清楚如何使这项工作,也找不到任何这样做的例子。
【问题讨论】:
【参考方案1】:@foreach (var propertyInfo in nfo)
<input type="text" class="form-control"
value="@propertyInfo.GetValue(SCustomer)"
@onchange="@((ChangeEventArgs __e) =>
propertyInfo.SetValue(SCustomer, __e.Value.ToString()))" />
【讨论】:
这可能缺少一个结束括号并给出以下错误:“System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'” 值得注意的是客户类的公共道具并不总是类型字符串。 (我会尝试更新问题以便提及)。 “文本”类型的输入值始终是一个字符串。切换属性类型并根据类型创建其他类型的输入。 我找到了一种方法,虽然它有点丑,但我自己的回答。谢谢你的帮助!它指导了我很多。另外,如果您在这个问题上有比我更好的工作解决方案,请发布它,我一定会接受它!【参考方案2】:@foreach(propertyInfo in nfo)
<label>@propertyInfo.Name</label>
<input type="text" value="@propertyInfo.GetValue(SCustomer)" @onchange="@((ChangeEventArgs __e) =>
propertyInfo.SetValue(SCustomer,Convert.ChangeType(__e.Value,
propertyInfo.PropertyType,null))"/>
【讨论】:
【参考方案3】:我终于找到了一种方法,这是我的解决方案: 我创建了一个助手类:
public class PropHolder
[Parameter]
public PropertyInfo info get; set;
[Parameter]
public string type get; set;
public PropHolder(PropertyInfo nfo, string propType)
info = nfo;
type = propType;
然后我创建了这个类的字典和一些检查函数(这是在 Clogic 内部)
[Parameter]
public Dictionary<int, PropHolder> Props get; set;
public void GetAllProps()
Props = new Dictionary<int, PropHolder>();
//nfo = SCustomer.GetType().GetProperties();
int Cid = 0;
foreach (PropertyInfo pif in SCustomer.GetType().GetProperties())
Props[Cid] = new PropHolder(pif, pif.PropertyType.Name);
Cid++;
public string CheckName(PropHolder propertyInfo)
if (propertyInfo.GetType() == typeof(PropHolder))
return propertyInfo.type;
else
return propertyInfo.GetType().Name.ToString();
public PropertyInfo getInfo(PropHolder propertyInfo)
if (propertyInfo.GetType() == typeof(PropHolder))
return propertyInfo.info;
else
return null;
最后我能够遍历我的字典的键并正确绑定所有值(从“来自火星的 agua”给出的答案中得到了很多帮助来解决这个问题) 这是 updateC.razor 内容:
@if (Props != null)
@foreach (int key in Props.Keys)
var pinfo = Props[key];
@if (CheckName(pinfo) == "String")
<input type="text" class="form-control" value=@(getInfo(pinfo).GetValue(SCustomer)) @onchange="@((ChangeEventArgs __e) => getInfo(pinfo).SetValue(SCustomer, __e.Value.ToString()))" />
这为每个字符串类型的道具提供了一个输入框,如果要处理其他类型,现在可以轻松添加它。这可能不是最好的解决方案,但它确实有效。如果发布任何更好的工作解决方案,我会更新答案。
【讨论】:
【参考方案4】:我使用泛型解决了这个问题。这让每个输入类型都传递一个泛型类型,该泛型类型定义了它想要使用的类型。
<input @bind="Name.Value" />
<input @bind="Age.Value" />
<div><code>Name</code>: @Name.Value</div>
<div><code>Age</code>: @Age.Value</div>
@code
private FormField<string> Name get; set; = new FormField<string>();
private FormField<int> Age get; set; = new FormField<int>();
public class Form
public ICollection<IFormField> Fields get; set;
public interface IFormField
public int ControlType get; set;
public class FormField<T> : IFormField
public int ControlType get; set;
public T Value get; set;
它在 BlazorFiddle 上:https://blazorfiddle.com/s/wen1g26q
【讨论】:
以上是关于使用 Blazor 将输入文本动态绑定到类/对象属性的主要内容,如果未能解决你的问题,请参考以下文章
Kivy,Python3.5 - 将用户文本输入绑定到类中的方法