如何在运行时将方法名称传递给 Blazor 中 DynamicComponent 生成的组件
How to pass method name at runtime to component generated by DynamicComponent in Blazor
我正在尝试使用 .Net 6 中的 DynamicComponent 在 Blazor Wasm 中呈现动态内容。要呈现的组件在具有以下结构的 JSON 文件中定义。
{
"type":"MyButton",
"parameters": {
"Label":"My Buttom",
"OnClicked": "DoAction"
}
}
DynamicComponent 允许我们使用 Dictionary 将参数传递给呈现的组件,如下面的代码我们可以将 component.parameters 定义为 Dictionary
<DynamicComponent Type=@component.type Parameters=@component.parameters />
在我的 razor 文件中,我定义了“DoAction()”方法。我希望在单击 MyButton 组件时调用此方法。但是我们如何将这个 DoAction() 方法作为 EventCallBack 传递给渲染的组件呢?
MyButton.razor 分量:
<button class="btn btn-primary" @onclick="HandledClicked">@LabelText</button>
@code{
[Parameter]
public string LabelText {get; set;}
[Parameter]
public EventCallback OnClicked { get; set; }
private void HandleClicked()
{
OnClicked.InvokeAsync();
}
}
DynamicPage.razor:(更新 #1)
@page "/DynamicPage"
@foreach (var component in components)
{
<DynamicComponent Type="component.Type" Parameters="component.Parameters" />
}
@code{
List<JsonComponent> components = new();
protected async override Task OnInitializedAsync()
{
var jsonComponentList = await Http.GetFromJsonAsync<List<JsonComponent>>("/data.json");
foreach (var item in jsonComponentList)
{
JsonComponent componentItem = new();
componentItem.Type = Type.GetType($"{nameSpaceComponents}{item.Type}");
componentItem.Parameters = new();
// below code to populate the component parameters as Dictionary<string, object>.
// the problem here is how to pass "DoAction()" method which is defined in the
// Json file to the rendered component by adding it to the paramater Dictionary<string, object>?
foreach (var kvp in item.Parameters)
{
var jsonElement = ((JsonElement)kvp.Value).GetString();
componentItem.Parameters.Add(kvp.Key, jsonElement);
}
}
}
public void DoAction()
{
//.. codes to perform some custom logic here when Button component is clicked.
}
}
JsonComponent.cs Class:
public class JsonComponent
{
public JsonComponent()
{
}
public Type Type { get; set; }
public Dictionary<string, object> Parameters { get; set; }
}
为了在运行时通过Dictionary 参数将方法或函数传递给动态生成的Component,我们需要使用EventCallback.Factory.Create()
方法创建一个EventCallBack。
我使用 foreach
循环获取 Json 文件中定义的参数列表,我们需要将其添加到 Dictionary 参数中。
然后我有一个if
条件来检查要传递给Component的参数是否是一个Event。在这里,我预定义了所有事件键名称应该以 'On' 作为前缀,例如'OnClicked'。如果参数是一个事件,那么我们创建一个 EventCallback
callback = EventCallBack.Factory.Create<string>(this, (Action<string>) this.GetType().GetMethod(kvp.Value.ToString()).CreateDelegate(typeof(Action<string>), this));
componentItem.Parameters.Add(kvp.Key, callback);
下面是 DynamicPage.razor 的代码:
@page "/DynamicPage"
@foreach (var component in components)
{
<DynamicComponent Type="component.Type" Parameters="component.Parameters" />
}
@code{
List<JsonComponent> components = new();
EventCallBack<string> callback; // Declare a EventCallBack variable use to pass to the generated Component
protected async override Task OnInitializedAsync()
{
var jsonComponentList = await Http.GetFromJsonAsync<List<JsonComponent>>("/data.json");
foreach (var item in jsonComponentList)
{
JsonComponent componentItem = new();
componentItem.Type = Type.GetType($"{nameSpaceComponents}{item.Type}");
componentItem.Parameters = new();
foreach (var kvp in item.Parameters)
{
var jsonElement = ((JsonElement)kvp.Value).GetString();
if (kvp.Key.ToString().StartsWith("On"))
{
callback = EventCallBack.Factory.Create<string>(this, (Action<string>) this.GetType().GetMethod(kvp.Value.ToString()).CreateDelegate(typeof(Action<string>), this));
componentItem.Parameters.Add(kvp.Key, callback);
}
else
{
componentItem.Parameters.Add(kvp.Key, jsonElement);
}
}
components.Add(componentItem);
}
}
}
我正在尝试使用 .Net 6 中的 DynamicComponent 在 Blazor Wasm 中呈现动态内容。要呈现的组件在具有以下结构的 JSON 文件中定义。
{
"type":"MyButton",
"parameters": {
"Label":"My Buttom",
"OnClicked": "DoAction"
}
}
DynamicComponent 允许我们使用 Dictionary
<DynamicComponent Type=@component.type Parameters=@component.parameters />
在我的 razor 文件中,我定义了“DoAction()”方法。我希望在单击 MyButton 组件时调用此方法。但是我们如何将这个 DoAction() 方法作为 EventCallBack 传递给渲染的组件呢?
MyButton.razor 分量:
<button class="btn btn-primary" @onclick="HandledClicked">@LabelText</button>
@code{
[Parameter]
public string LabelText {get; set;}
[Parameter]
public EventCallback OnClicked { get; set; }
private void HandleClicked()
{
OnClicked.InvokeAsync();
}
}
DynamicPage.razor:(更新 #1)
@page "/DynamicPage"
@foreach (var component in components)
{
<DynamicComponent Type="component.Type" Parameters="component.Parameters" />
}
@code{
List<JsonComponent> components = new();
protected async override Task OnInitializedAsync()
{
var jsonComponentList = await Http.GetFromJsonAsync<List<JsonComponent>>("/data.json");
foreach (var item in jsonComponentList)
{
JsonComponent componentItem = new();
componentItem.Type = Type.GetType($"{nameSpaceComponents}{item.Type}");
componentItem.Parameters = new();
// below code to populate the component parameters as Dictionary<string, object>.
// the problem here is how to pass "DoAction()" method which is defined in the
// Json file to the rendered component by adding it to the paramater Dictionary<string, object>?
foreach (var kvp in item.Parameters)
{
var jsonElement = ((JsonElement)kvp.Value).GetString();
componentItem.Parameters.Add(kvp.Key, jsonElement);
}
}
}
public void DoAction()
{
//.. codes to perform some custom logic here when Button component is clicked.
}
}
JsonComponent.cs Class:
public class JsonComponent
{
public JsonComponent()
{
}
public Type Type { get; set; }
public Dictionary<string, object> Parameters { get; set; }
}
为了在运行时通过DictionaryEventCallback.Factory.Create()
方法创建一个EventCallBack。
我使用 foreach
循环获取 Json 文件中定义的参数列表,我们需要将其添加到 Dictionary
然后我有一个if
条件来检查要传递给Component的参数是否是一个Event。在这里,我预定义了所有事件键名称应该以 'On' 作为前缀,例如'OnClicked'。如果参数是一个事件,那么我们创建一个 EventCallback
callback = EventCallBack.Factory.Create<string>(this, (Action<string>) this.GetType().GetMethod(kvp.Value.ToString()).CreateDelegate(typeof(Action<string>), this));
componentItem.Parameters.Add(kvp.Key, callback);
下面是 DynamicPage.razor 的代码:
@page "/DynamicPage"
@foreach (var component in components)
{
<DynamicComponent Type="component.Type" Parameters="component.Parameters" />
}
@code{
List<JsonComponent> components = new();
EventCallBack<string> callback; // Declare a EventCallBack variable use to pass to the generated Component
protected async override Task OnInitializedAsync()
{
var jsonComponentList = await Http.GetFromJsonAsync<List<JsonComponent>>("/data.json");
foreach (var item in jsonComponentList)
{
JsonComponent componentItem = new();
componentItem.Type = Type.GetType($"{nameSpaceComponents}{item.Type}");
componentItem.Parameters = new();
foreach (var kvp in item.Parameters)
{
var jsonElement = ((JsonElement)kvp.Value).GetString();
if (kvp.Key.ToString().StartsWith("On"))
{
callback = EventCallBack.Factory.Create<string>(this, (Action<string>) this.GetType().GetMethod(kvp.Value.ToString()).CreateDelegate(typeof(Action<string>), this));
componentItem.Parameters.Add(kvp.Key, callback);
}
else
{
componentItem.Parameters.Add(kvp.Key, jsonElement);
}
}
components.Add(componentItem);
}
}
}