我正在使用下面的递归函数来尝试呈现一个html手风琴。它使用反射来收集给定对象的所有属性名称和值。对象是未知深度/子级等的数据树结构。
@* Accordoin HTML Template *@
<div class="accordion">
<input type="checkbox" id="accordion-1" name="accordion-checkbox" hidden>
<label class="accordion-header" for="accordion-1">
<i class="icon icon-arrow-right mr-1"></i>
Title
</label>
<div class="accordion-body">
<!-- Accordions content -->
</div>
</div>
@code {
public void BuildTree(object obj)
{
if (obj == null) return;
Type objType = obj.GetType();
PropertyInfo[] properties = objType.GetProperties();
foreach (PropertyInfo property in properties)
{
object propValue = property.GetValue(obj, null);
if (property.PropertyType.IsPrimitive || property.PropertyType == typeof(string))
{
//Build accordion body
}
else if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
{
//Build accordion header
IEnumerable enumerable = (IEnumerable)propValue;
if (enumerable != null)
foreach (object child in enumerable)
BuildTree(child);
}
else
{
//Build accordion header
BuildTree(propValue);
}
}
}
我的问题是如何以递归的方式呈现html
我尝试使用RenderFragment如下:
RenderFragment BuildTree(object obj)
{
if (obj == null) return @<p>test</p>;
Type objType = obj.GetType();
PropertyInfo[] properties = objType.GetProperties();
foreach (PropertyInfo property in properties)
{
object propValue = property.GetValue(obj, null);
if (property.PropertyType.IsPrimitive || property.PropertyType == typeof(string))
{
return @<p>Some test markup</p>
}
else if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
{
IEnumerable enumerable = (IEnumerable)propValue;
if (enumerable != null)
foreach (object child in enumerable)
BuildTree(child);
}
else
{
BuildTree(propValue);
}
}
return @<p>Done</p>;
}
它构建但在运行时出现错误:
未处理的异常呈现组件:无法绑定到目标方法,因为其签名与委托类型的签名不兼容
我知道在blazor中一定有一种惯用的方法可以做到这一点,但我无法理解递归如何处理渲染片段。
My2美分:组件可以自嵌套。对我的大脑来说,这是渲染嵌套组件的最简单方法——一种非常物理的递归。我正在工作,所以我无法为您完成一个有效的解决方案,但希望以下模板足够清晰。如果希望显示所有分支,则完全删除布尔逻辑或将ShowChildren初始化为true而不是false;
Nestable.Razar
@if(ChildCollection is not null){
<div @onclick=ToggleVisibility >
<u>@DisplayForThisObject</u>
</div>
@if(ShowChildren){
foreach (var Child in ChildCollection){
<Nestable PassedObject=Child />
}
}
}
else {
@DisplayForThisObject;
}
@code {
[Parameter]
public object PassedObject {get; set;}
IEnumerable<object> ChildCollection {get; set;}
string DisplayForThisObject {get; set;}
bool ShowChildren {get; set;} = false;
protected override void OnInitialized()
{
DisplayForThisObject = SomePropertyToString();
ChildCollection = SomemethodToGetTheChildObjects(PassedObject);
base.OnInitialized();
}
void ToggleVisibility(){
ShowChildren = !ShowChildren;
}
}