Есть ли способ сделать двустороннюю привязку в blazor inputtext динамически

Я пытаюсь создать многоразовый элемент управления. Я понял, как обрабатывать сценарии только для чтения, используя отражения с помощью @typeof(TItem).GetProperty(col.PropertyName).GetValue(item)

И теперь я хочу сделать то же самое с двухсторонней привязкой Нравится <InputText @bind-Value = "item.{select a property using the PropertyName value in ColumnDefinition}</InputText>"

Есть ли способ выбрать свойство элемента с помощью строки?

Спасибо!

Дополнительные ссылки ниже:

@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; }
    }

🤔 А знаете ли вы, что...
C# позволяет создавать собственные библиотеки классов и использовать их в других проектах.


1
2 422
3

Ответы:

Вы можете получить значение свойства любого объекта на основе имени самого свойства.

Пример

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; }
}

Теперь вы можете просто адаптировать это решение к вашему случаю

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

Надеюсь, это сработает, я не так много работаю с файлами бритвы и не могу проверить этот случай прямо сейчас, но, по крайней мере, это может привести вас к решению.


В Blazor двусторонняя привязка состоит из двух шагов.

  1. В процессе рендеринга значение будет прочитано и отображено.
  2. Он подпишется на событие изменения компонента. Обработчик запишет значение обратно в ваше свойство.

Чтобы позволить компилятору творить чудеса, вы используете @bind-Value вместо Value. Однако вы можете «взломать» систему, установив обработчик событий самостоятельно.

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

В качестве справки взгляните на https://learn.microsoft.com/en-us/aspnet/core/blazor/components/data-binding?view=aspnetcore-5.0.


Решено

<InputText> отличается от <input>

<InputText> требует Value, ValueChanged и ValueExpression.

@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));
    }
}

Используя вышеуказанный компонент, вы можете сделать

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

Обязательно заверните <EditForm>