简体   繁体   English

如何以动态形式使用@bind-Value?

[英]How to use @bind-Value in a dynamic form?

I am using Blazor to create a dynamic form from the properties of my model.我正在使用 Blazor 从我的 model 的属性创建动态表单。

I am using a for each loop to loop through the properties of the model.我正在使用for each循环来遍历 model 的属性。

public class SensorType
{
    public int Id { get; set; }
    [Required]
    [MaxLength(30)]
    [Display(Name = "Sensor Type Name")]
    public string Name { get; set; }
    [Required]
    [MaxLength(500)]
    public string Description { get; set; }
    [Required]
    [MaxLength(2048)]
    [Display(Name = "Datasheet URL")]
    public string DatasheetUrl { get; set; }
}

I implemented this razor view, where I try to bind to public SensorType sensortype { get; set; }我实现了这个 razor 视图,我尝试绑定到public SensorType sensortype { get; set; } public SensorType sensortype { get; set; } public SensorType sensortype { get; set; } . public SensorType sensortype { get; set; } But I need to bind to sensortype.property where property is whatever property the model has that is in the for each loop.但是我需要绑定到 sensortype.property ,其中 property 是 model 在 for each 循环中具有的任何属性。 But I cannot simply just call say @bind-Value="sensortype.property" .但我不能简单地打电话说@bind-Value="sensortype.property" Any ideas on how to do this?关于如何做到这一点的任何想法? I don't want to have to manually type every field.我不想手动输入每个字段。 Thanks!谢谢!

<EditForm Model="@sensortype" OnValidSubmit="@SaveSensorType">

@foreach(var property in typeof(SensorType).GetProperties())
{
    if(property.Name == "Id")
    {
        continue;
    }
    <div class="form-group row">
        <label class="col-sm-2 col-form-label">@(GetAttribute(property, false)) </label> //This function get the name of the property in a human-readable way.
        <div class="col-sm-10">//I would like to bind here to sensortype's property in the for each loop but sensortype.property gives me an error.
            <InputTextArea class="form-control" @bind-Value="sensortype.property" value="sensortype.property.Name" placeholder="Description of the Type of Sensor" /> 
        </div>
    </div>
}

I am playing this days with blazor and I made a kind of DynamicForm, is not perfect but is working.这几天我正在玩 blazor 并且我制作了一种 DynamicForm,虽然不完美但正在工作。 I just want to show you my dynamic form as proof of concept, not at something which I wold use in production.我只是想向您展示我的动态形式作为概念证明,而不是我将在生产中使用的东西。

Basicly we want to write something like this:基本上我们想写这样的东西:

<DynamicForm @bind-Model="MySensorType" /> 

//this will generate a form with fields for all properties of the model

So, on Index view let's create a property for MySensorType and some markup to see if the model is changing when the form fields are edited.因此,在索引视图中,让我们为 MySensorType 创建一个属性和一些标记,以查看编辑表单字段时 model 是否发生变化。

@page "/"

    <div style="display:flex">
        <div> 
            <DynamicForm @bind-Model="MySensorType" />
        </div>

        <div style="background:yellow;flex:1;margin:20px;">
            <p>Id: @MySensorType.Id</p>
            <p>Name: @MySensorType.Name</p>
            <p>Description: @MySensorType.Description</p>
            <p>Url: @MySensorType.DatasheetUrl</p>
        </div>
    </div>

@code {
    public SensorType MySensorType { get; set; } = new SensorType();


    public class SensorType
    {
        public int Id { get; set; } = 1;
        public string Name { get; set; } = "Some Name";
        public string Description { get; set; } = "Some Description";
        public string DatasheetUrl { get; set; } = "This is a URL";
    }
} 

In order to generate automatically the fields, we need some kind of DynamicField.为了自动生成字段,我们需要某种 DynamicField。 Below component is for named "DynamicField"下面的组件用于命名为“DynamicField”

    <div>
        <label>@Caption</label>
        @if (Value is String sValue)
        {
            <input type="text" value="@sValue" @onchange="OnChange"/>
        }
        @if (Value is int iValue)
        {
            <input type="number" value="@iValue" @onchange="OnChange" />
        }

    </div>

@code {
    [Parameter] public string Caption { get; set; }
    [Parameter] public object Value { get; set; }
    [Parameter] public EventCallback<object> ValueChanged { get; set; }

   async void OnChange(ChangeEventArgs e)
    {
       await ValueChanged.InvokeAsync(e.Value);
    }
}

Now, we can create the wrapper so called DynamicForm:现在,我们可以创建名为 DynamicForm 的包装器:

@typeparam T


    @foreach (var p in Properties)
    {
        <DynamicField Value="@p.Value" Caption="@p.Key" ValueChanged="@((e)=>OnValueChanged(e,p.Key))"/>
    }


@code{
    [Parameter] public T Model { get; set; }
    [Parameter] public EventCallback<T> ModelChanged { get; set; }
    public Dictionary<string, object> Properties { get; set; } = new Dictionary<string, object>();

    protected override void OnInitialized()
    {
        var props = Model.GetType().GetProperties();
        foreach (var p in props)
        {
            Properties.Add(p.Name, p.GetValue(Model));
        }
    }

    void OnValueChanged(object e, string prop)
    {
        var p = Model.GetType().GetProperty(prop);
        if (p.PropertyType == typeof(int))
        {
            var intValue = Convert.ToInt32(e);
            p.SetValue(Model, intValue);
        }
        if (p.PropertyType == typeof(string))
        {
            p.SetValue(Model, e.ToString());
        }

        ModelChanged.InvokeAsync(Model);
    }
}

What actually is happening here, we are using Reflection to get all properties of the model, send them to DynamicFields, and when those values are changed we set the new value to the model and call ModelChanged to send new values.这里实际发生了什么,我们使用反射来获取 model 的所有属性,将它们发送到 DynamicFields,当这些值发生更改时,我们将新值设置为 model 并调用 ModelChanged 以发送新值。

On my computer this works, and every time when I change a value, MySensorType is showing the new value on Index component.在我的计算机上这是可行的,每次我更改值时,MySensorType 都会在 Index 组件上显示新值。

在此处输入图像描述

You can see that I created dynamic fields only for Number and String, if you have DateTime or Select, you need to extend this DynamicField, for select will be more difficult.你可以看到我只为Number和String创建了动态字段,如果你有DateTime或者Select,你需要扩展这个DynamicField,因为select会比较困难。

By the way, on Index view you can put a button and call SaveChanges with your logic and use MySensorType.顺便说一句,在索引视图上,您可以放置一个按钮并使用您的逻辑调用 SaveChanges 并使用 MySensorType。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 对两个属性使用相同的绑定值 - Use the same bind-Value for two properties 如何动态生成 blazor 的 @bind-Value? - How to generate dynamically blazor's @bind-Value? 如何将绑定值和 onchange 放在同一个输入复选框中? - how to put a bind-value and an onchange in the same input checkbox? 如何使用表单提交的绑定值为 InputText 设置占位符? - How to set placeholder for InputText with bind-Value for formsubmit? @bind 和 @bind-value 之间的区别 - Difference between @bind and @bind-value Blazor 绑定值:输入事件 - Blazor bind-value:event oninput 一种捕获输入的形式,但有两种不同的模型(使用 bind-Value 进行类型转换失败) - One form to capture input but two different models (typecasting with bind-Value fails) 为什么我的 blazor 的 @bind-value 返回错误? - Why does my @bind-value of my blazor returns an error? 在 blazor 应用程序中使用 MudTextField 会返回错误:“无法从绑定属性 &#39;bind-Value&#39; 推断属性名称。” - Using MudTextField in a blazor app returns an error : 'The attribute names could not be inferred from bind attribute 'bind-Value'.' 为什么 value=&quot;string-value&quot; 与 input type=&quot;time&quot; 一起工作,而不是 bind-value=&quot;string-value&quot; - Why does value="string-value" work with input type="time", but not bind-value="string-value"
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM