Blazorで動的なフォームを作成しようとしていますが、行き詰まっています。 2つの入力パラメーターを受け取るFormFactoryコンポーネントがあります。データバインディングのモデルと、作成する要素を定義するディクショナリ。アイデアはモデルオブジェクトを渡すことです
public class Data
{
public string Name { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
}
そして辞書
{ "Name": "string" },
{ "Phone": "string" }
モデルのプロパティにバインドされたNameとPhoneの2つの入力フィールドを持つフォームを作成します。
<h3>Dynamic form</h3>
<EditForm Model="@DataContext">
@foreach (var field in FieldIdentifiers)
{
if (field.Value == "string")
{
<InputText @bind-Value="DataContext.GetType().GetProperty(field.Key).GetValue(DataContext, null).ToString()"></InputText>
}
}
</EditForm>
@code {
[Parameter] public object DataContext { get; set; }
[Parameter] public Dictionary<string, string> FieldIdentifiers { get; set; }
}
しかし、これは機能しません。私は言ってエラーが出ます
"ブロック内の一部の戻り値の型がデリゲートの戻り値の型に暗黙的に変換できないため、ラムダ式を意図したデリゲート型に変換できません"および "割り当ての左側の側は変数、プロパティ、またはインデクサーである必要があります"
編集:Blazorがエラーの原因となるValueChanged属性を生成することがわかりました
builder2.AddAttribute(8, "ValueChanged", Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck<Microsoft.AspNetCore.Components.EventCallback<System.String>>(Microsoft.AspNetCore.Components.EventCallback.Factory.Create<System.String>(this, Microsoft.AspNetCore.Components.EventCallback.Factory.CreateInferred(this, __value => DataContext.GetType().GetProperty(field.Key).GetValue(DataContext, null).ToString() = __value, DataContext.GetType().GetProperty(field.Key).GetValue(DataContext, null).ToString()))));
それは機能しないので、RenderFragmentを作成して、次のようにコンポーネントを変更しました
<h3>Dynamic form</h3>
@MyForm()
@code {
[Parameter] public object DataContext { get; set; }
[Parameter] public Dictionary<string, string> FieldIdentifiers { get; set; }
RenderFragment MyForm() => builder =>
{
builder.AddMarkupContent(0, "<h3>Dynamic form</h3>\r\n");
builder.OpenComponent<Microsoft.AspNetCore.Components.Forms.EditForm>(1);
builder.AddAttribute(2, "Model", Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck<System.Object>(DataContext));
builder.AddAttribute(3, "ChildContent", (Microsoft.AspNetCore.Components.RenderFragment<Microsoft.AspNetCore.Components.Forms.EditContext>)((context) => builder2 =>
{
builder2.AddMarkupContent(4, "\r\n");
foreach (var field in FieldIdentifiers)
{
if (field.Value == "string")
{
builder2.AddContent(5, " ");
builder2.OpenComponent<Microsoft.AspNetCore.Components.Forms.InputText>(6);
builder2.AddAttribute(7, "Value", Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck<System.String>(Microsoft.AspNetCore.Components.BindMethods.GetValue(DataContext.GetType().GetProperty(field.Key).GetValue(DataContext, null).ToString())));
builder2.AddAttribute(8, "ValueChanged", Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck<Microsoft.AspNetCore.Components.EventCallback<System.String>>(Microsoft.AspNetCore.Components.EventCallback.Factory.Create<System.String>(this, Microsoft.AspNetCore.Components.EventCallback.Factory.CreateInferred(this, __value => DataContext.GetType().GetProperty(field.Key).SetValue(DataContext, __value), DataContext.GetType().GetProperty(field.Key).GetValue(DataContext, null).ToString()))));
builder2.AddAttribute(9, "ValueExpression", Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck<System.Linq.Expressions.Expression<System.Func<System.String>>>(() => Convert.ToString(DataContext.GetType().GetProperty(field.Key).GetValue(DataContext, null))));
builder2.CloseComponent();
builder2.AddMarkupContent(10, "\r\n");
}
}
builder2.AddMarkupContent(11, "\r\n");
}));
builder.CloseComponent();
};
}
これはコンパイルされますが、実行時エラーが発生します
System.ArgumentException:指定された式に、サポートされていないMethodCallExpression1が含まれています。 FieldIdentifierは、オブジェクトの単純なメンバーアクセサー(フィールド、プロパティ)のみをサポートします。
どんな助けでもいただければ幸いです
調査中にこれに遭遇しましたが、結局@bind-value
およびvalue
およびonchanged
を直接使用して、リフレクションを介してプロパティを設定します。
@foreach (var p in Datacontext.GetType().GetProperties())
{
<input type="text"
placeholder="@p.Name"
value="@p.GetValue(Datacontext)"
@onchange="(e) => p.SetValue(Datacontext, e.Value)">
}
このコードは、プロパティのタイプ変換を行わず、onchangeハンドラーでプロパティオブジェクトに対するクロージャーを使用することを示しています。
おそらく誰かがそれを便利だと思うでしょう:)