我试图使用Blazor为类内的属性构建一个输入字段的动态列表,但无法确定如何将输入框的内容绑定/链接到类的属性(类可以有大量的公共道具,而不仅仅是下面例子中的名称和描述,它们并不总是"字符串"类型(
假设我有这个类/型号:
public class customer{
public string Name { get; set; }
public int Age { get; set; }
public string Description { get; set; }
}
我得到了这个blazor组件(更新C.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内部的值在输入完成后不会更改。我猜我完全错了,但似乎不知道如何做到这一点,也找不到任何这样做的例子。
@foreach (var propertyInfo in nfo)
{
<input type="text" class="form-control"
value="@propertyInfo.GetValue(SCustomer)"
@onchange="@((ChangeEventArgs __e) =>
propertyInfo.SetValue(SCustomer, __e.Value.ToString()))" />
}
@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))"/>
}
我终于找到了一种方法,下面是我的解决方案:我创建了一个助手类:
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;
}
}
最后,我能够循环遍历字典的键并正确绑定所有值(从answer中得到了很多帮助:"agua from mars"(这是更新C.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()))" />
}
}
}
这为每个String类型的道具提供了一个输入框,如果要处理其他类型,现在可以很容易地添加。这可能不是最好的解决办法,但确实有效。如果有更好的工作解决方案发布,我会更新答案。
我使用泛型解决了这个问题。这允许每个输入类型传递一个泛型类型,该类型定义了它想要使用的类型。
<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