Использование привязки модели к объекту дерева и рекурсивного рендеринга на страницах Razor?

#asp.net #razor-pages #model-binding

Вопрос:

У меня есть этот урок:

 public class SmartNode
{
    public string Key { get; set; }
    public object Value { get; set; }
    public JsonValueKind ValueKind { get; set; }
    public bool IsFinal { get; set; }
    public int Level { get; set; }
    public SmartNode ParentNode { get; set; }
    public List<SmartNode> SubNodes { get; set; } = new List<SmartNode>();
}
 

IsFinal означает, что объект представляет собой простой узел JSON (строка, логическое значение или число..), если IsFinal значение равно false, я выполняю рекурсию, чтобы получить «окончательные» свойства:

а вот страница с бритвой:

 @page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

@{
    if (Model.HeadNode != null)
    {
        using (Html.BeginForm())
        {
            await DrawNode(Model.HeadNode);

            async Task DrawNode(SmartNode node)
            {
                var margin = (node.Level * 20).ToString()   "px";
                if (!node.IsFinal)
                {
                    <h4 style="margin-left:@margin">@node.Key</h4>
                    foreach (var subnode in node.SubNodes)
                    {
                        await DrawNode(subnode);
                    }
                }
                else
                {
                    int i = 0;//temp
                    var id = node.Key   "_"   node.Level;
                    <div>
                        <label for="@id" style="margin-left: @margin">@node.Key</label>
                        @switch (node.ValueKind)
                        {
                            case System.Text.Json.JsonValueKind.Undefined:
                                break;
                            case System.Text.Json.JsonValueKind.Object:
                                break;
                            case System.Text.Json.JsonValueKind.Array:
                                break;
                            case System.Text.Json.JsonValueKind.String:
    
                                <input type="text" name="???.Value" value="@node.Value" id="@id" />
                                break;
                            case System.Text.Json.JsonValueKind.Number:
                                <input type="number" name="???.Value" value="@node.Value" id="@id" />

                                break;
                            case System.Text.Json.JsonValueKind.True:
                            case System.Text.Json.JsonValueKind.False:
                                <input type="checkbox" name="???.Value"
                                       checked="@(node.Value.ToString() == "True")"
                                       value="True" id="@id" />
                                <input name="???.Value" type="hidden" value="False">
                                break;
                            case System.Text.Json.JsonValueKind.Null:
                                <input type="text" name="???.Value" value="@node.Value" id="@id" />
                                break;
                            default:
                                break;
                        }
                    </div>
                }

            }

            <button type="submit">Save</button>
        }
    }
}
 

Проблема в том, как я могу назначить входное имя из razor

Я использую страницы .NET 5 Razor.

Комментарии:

1. Не могли бы вы избавиться от IsFinal этого и просто использовать SubNodes.Count() == 0 вместо этого?

2. Да, я мог бы, но я об этом не подумал

Ответ №1:

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

Поздравляю, теперь у вас есть рекурсивный компонент.

Edit1: Компонент (Здесь SmartTreeView.razor) будет выглядеть примерно так:

 <!-- Maybe some title per node, whatever -->
<h3>@Node.Key - @Node.Value</h3>

<!-- Render node data here, like -->
@if (Node.Value != null)
{
    <DataComponent data="@(Node.Value)" />
}

<!-- Then, recursion -->
@foreach (var node in Node.SubNodes)
{
    <span>@tab</span>
    <SmartTreeView Node="@(node)" />
}



@code {
    private const string tab = "t";

    [Parameter]
    public SmartNode Node { get; set; }

}
 

Затем страница просто помещается <SmartTreeView Node="@(Model.HeadNode)" /> куда угодно.

Комментарии:

1. Вы имеете в виду компоненты представления?

2. Да, вы бы включили его, как <vc:custom-tree root="Model.HeadNode"></vc:custom-tree>

3. разве я не должен отправлять текущий узел, а не все дерево? , например: root:"node" , но я полагаю, что отправка объектов в VC невозможна

4. Ваша страница имеет только один узел: корневой или, в вашем случае, головной. Рекурсия происходит только в компоненте.

5. Не могли бы вы привести пример? Я попытался изложить ваше предложение в коде, но оно не сработало, в итоге я получил тот же результат без компонента представления. Я не понял «и сделать так, чтобы компонент содержал экземпляры самого себя для каждого дочернего узла».