#c# #html #asp.net-core #blazor
#c# #HTML #asp.net-core #blazor
Вопрос:
Я пытаюсь создать многоразовый элемент управления. Я выяснил, как обрабатывать сценарии только для чтения, используя отражения с @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; }
}
Ответ №1:
Вы можете получить значение из свойства любого объекта на основе имени самого свойства.
Пример
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>
Надеюсь, это сработает, я не так много работаю с файлами razor и не могу протестировать этот случай прямо сейчас, но, по крайней мере, это может привести вас к решению
Комментарии:
1. Привет, спасибо за ответ, но я не думаю, что это сработает. Ваше предложение по сути такое же, как у моего @typeof(TItem). getProperty(col.propertyName). Получить значение (элемент). Чего я хотел бы добиться, так это двусторонней привязки, и, насколько я понимаю, это означает, что мне нужно как получить, так и установить свойство. Я все еще тестировал ваш код, но он не сработал.
Ответ №2:
В Blazor двусторонняя привязка состоит из двух шагов.
- В процессе рендеринга значение будет считано и отображено.
- Он будет подписываться на событие изменения компонента. Обработчик запишет значение обратно в ваше свойство.
Чтобы позволить компилятору творить чудеса, вы используете @bind-Value
вместо Value
. Однако вы можете «взломать» систему, самостоятельно установив обработчик событий.
<InputText
Value="@typeof(TItem).GetProperty(col.PropertyName).GetValue(item)"
ValueChanged="@(e => typeof(TItem).GetProperty(col.PropertyName).SetValue(item,e))">
</InputText>
В качестве ссылки взгляните на https://docs.microsoft.com/en-us/aspnet/core/blazor/components/data-binding?view=aspnetcore-5.0 .
Ответ №3:
<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>