简体   繁体   English

有没有办法在 blazor inputtext 中动态进行双向绑定

[英]Is there a way to do two-way binding in blazor inputtext dynamically

I am trying to create a reusable control.我正在尝试创建一个可重用的控件。 I have figured out how to handle the read-only scenarios using reflections with @typeof(TItem).GetProperty(col.PropertyName).GetValue(item)我已经弄清楚如何使用@typeof(TItem).GetProperty(col.PropertyName).GetValue(item)的反射来处理只读场景

And now I want to do the same with two-way binding Like <InputText @bind-Value="item.{select a property using the PropertyName value in ColumnDefinition}</InputText>"现在我想对双向绑定做同样的事情,比如<InputText @bind-Value="item.{select a property using the PropertyName value in ColumnDefinition}</InputText>"

Is there a way to select the item's property using a string?有没有办法使用字符串 select 项目的属性?

Thanks!谢谢!

More references below:更多参考如下:

@typeparam TItem
<EditForm>
    <table>
        <thead>
            <tr>
                <Virtualize Items="ColumnDefinitions" Context="col">
                    <th>
                        @col.Caption
                    </th>
                </Virtualize>
            </tr>
        </thead>
        <tbody>
            <Virtualize Items="Items" Context="item">
                <tr>
                    <Virtualize Items="ColumnDefinitions" Context="col">
                        <td>
                            @typeof(TItem).GetProperty(col.PropertyName).GetValue(item)
                            <InputText @bind-Value=""></InputText>
                        </td>
                    </Virtualize>
                </tr>
            </Virtualize>
        </tbody>
    </table>
</EditForm>


@code {
    [Parameter] public List<ColumnDefinition> ColumnDefinitions { get; set; }
    [Parameter] public List<TItem> Items { get; set; }
}

    public class ColumnDefinition
    {
        public short Order { get; set; }
        public string Caption { get; set; }
        public bool IsReadOnly { get; set; } = true;
        public InputTypeEnum InputType { get; set; } = InputTypeEnum.Text;
        public string PropertyName { get; set; }
    }

You can get a value from a property on any object based on the name of the property itself.您可以根据属性本身的名称从任何 object 上的属性中获取值。

Example例子

public class Program
{
    public static void Main()
    {
        var tst = new MyClass { MyProperty = 1 };           
        var propValue = tst.GetType().GetProperties().FirstOrDefault(p => p.Name == "MyProperty").GetValue(tst);
        Console.WriteLine(propValue);           
    }           
}

public class MyClass {
    public int MyProperty { get;set; }
}

Now you can just adapt this solution to your case现在您可以根据您的情况调整此解决方案

<Virtualize Items="ColumnDefinitions" Context="col">
    <td>                            
        <InputText @bind-Value="@typeof(TItem).GetProperties().FirstOrDefault(p => p.Name == col.PropertyName).GetValue(item);"></InputText>
    </td>
</Virtualize>

Hope this works, i dont work as much with razor files and cannot test this case right now, but at leats it can lead you to a solution希望这可行,我对 razor 文件的工作量不大,现在无法测试这种情况,但至少它可以引导您找到解决方案

In Blazor, a two-way binding consists of two steps.在 Blazor 中,双向绑定包括两个步骤。

  1. In the render process, the value will be read and displayed.在渲染过程中,将读取并显示该值。
  2. It will subscribe to the change event of the component.它将订阅组件的更改事件。 The handler will write the value back to your property.处理程序会将值写回您的属性。

To let the compiler do the magic, you use @bind-Value instead of Value .为了让编译器发挥作用,您可以使用@bind-Value而不是Value However, you could "hack" the system by setting the event handler by yourself.但是,您可以通过自己设置事件处理程序来“破解”系统。

<InputText 
   Value="@typeof(TItem).GetProperty(col.PropertyName).GetValue(item)" 
   ValueChanged="@(e => typeof(TItem).GetProperty(col.PropertyName).SetValue(item,e))">
</InputText>

As a reference, have a look at https://docs.microsoft.com/en-us/aspnet/core/blazor/components/data-binding?view=aspnetcore-5.0 .作为参考,请查看https://docs.microsoft.com/en-us/aspnet/core/blazor/components/data-binding?view=aspnetcore-5.0

<InputText> is different from <input> <InputText>不同于<input>

<InputText> requires Value , ValueChanged and ValueExpression . <InputText>需要ValueValueChangedValueExpression

@typeparam TItem
@using System.Linq.Expressions

<InputText Value="@Value"
           ValueChanged="@ValueChanged"
           ValueExpression="@ValueExpression"
           class="form-control">
</InputText>

@code {
    [Parameter] public TItem Item { get; set; }
    [Parameter] public string PropertyName { get; set; }
    private string Value;
    private EventCallback<string> ValueChanged;
    private Expression<Func<string>> ValueExpression;

    protected override void OnInitialized()
    {
        Value = typeof(TItem).GetProperty(PropertyName).GetValue(Item).ToString();
        ValueChanged = Microsoft.AspNetCore.Components.EventCallback.Factory.Create<System.String>(Item, Microsoft.AspNetCore.Components.EventCallback.Factory.CreateInferred(Item, _value => typeof(TItem).GetProperty(PropertyName).SetValue(Item, _value), (string)typeof(TItem).GetProperty(PropertyName).GetValue(Item)));
        ValueExpression = Expression.Lambda<Func<string>>(Expression.Property(Expression.Constant(Item, typeof(TItem)), PropertyName));
    }
}

Using the above component you can then do使用上面的组件,你可以做

<CustomInputText TItem="TItem" Item="item" PropertyName="@col.PropertyName">

Make sure to wrap in in <EditForm>确保包含在<EditForm>

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM