使用for循环渲染树视图

本文关键字:视图 for 循环 使用 | 更新日期: 2023-09-27 18:04:25

我有这个类:

public class SortOrderModel
{
    public string IdSort { get; set; }
    public List<ContentPage> ContentPages { get; set; }
}

上面有listproperty的类是这个类的列表:

public class ContentPage
{
public string Id { get; set; }
public string ParentReference { get; set; }
public string Title { get; set; }
public string SortOrder { get; set; }
}

假设我把SortOrderModel作为@model发送给视图

在view: Model中。ContentPages,是一个包含5个ContentPage的列表,其值为:

var home = new ContentPage()
{
    Id = "ContentPages/1",
    Title = "Home",
    ParentReference = "/",
    SortOrder = "0"
};
var about = new ContentPage()
{
    Id = "ContentPages/2",
    Title = "About",
    ParentReference = "ContentPages/1",
    SortOrder = "1"
};
var contactinfo = new ContentPage()
{
    Id = "ContentPages/3",
    Title = "ContactInfo",
    ParentReference = "ContentPages/2",
    SortOrder = "0"
};
var allProducts = new ContentPage()
{
    Id = "ContentPages/4",
    Title = "AllProducts",
    ParentReference = "ContentPages/1",
    SortOrder = "2"
};
var product1 = new ContentPage()
{
    Id = "ContentPages/5",
    Title = "Product1",
    ParentReference = "ContentPages/4",
    SortOrder = "0"
};
    var product2 = new ContentPage()
{
    Id = "ContentPages/6",
    Title = "Product1",
    ParentReference = "ContentPages/4",
    SortOrder = "1"
};

我如何使用for循环渲染这些值的树视图,所以它看起来像这样:

> Home
    > About
        > ContactInfo
    > AllProducts
        > Product1
        > Product2

使用for循环非常重要,因为我将在带有@Html的视图中使用它。用于sororder - properties的TextBoxFor,这样我就可以更改每个对象的sortOrder值。据我所知,我需要使用for循环而不是foreach来获得模型绑定工作,因为我正在将值发送到[HttpPost]方法。

这是我的尝试:

@model CMS_Affiliate_Web.Models.SortOrderModel
@{
string startPageId = "";
foreach (var pageId in Model.ContentPages.Where(o => o.Url == "/").Select(o => o.Id))
{
    startPageId = pageId;
}
}
<ul>
    <li>
        <div>
            @using (Html.BeginForm("SortOrderMenu", "secure", Model.ContentPages, FormMethod.Post))
        {
            @Html.HiddenFor(o => Model.IdSort)
            var contentPages = Model.ContentPages.ToList();
            for (int i = 0; i < contentPages.Count(); i++)
            {
                <ul>
                    @if (Model.ContentPages[i].Url == "/" || Model.ContentPages[i].ParentReference == startPageId)
                    {
                        <li>@Model.ContentPages[i].Title @Html.TextBoxFor(o => Model.ContentPages[i].SortOrder, new {@class = "sortBox"})</li>
                    }
                    else if (contentPages.Any(m => m.Id == contentPages[i].ParentReference))
                    {
                        <li style="padding-left: 80px; color: red;">@Model.ContentPages[i].Title @Html.TextBoxFor(o => Model.ContentPages[i].SortOrder, new {@class = "sortBox"})</li>
                    }
                </ul>
            }
            <div class="activity-desk">
                <input type="submit" value="Spara ny sortering" class="btn btn-primary" name="saveSliders" />
            </div>
        }
    </div>
</li>

但是它呈现的是这样的,不是我想要的:

> Home
    > About
    > AllProducts
        > Product1
        > Product2
        > ContactInfo

编辑!

@model Models.SortOrderModel
@{
ViewBag.Title = "SortOrderMenu";
Layout = "~/Views/Shared/_Layout.cshtml";
}

@helper RenderItems(string parentID, int indent = 0)
{
@Html.HiddenFor(o => Model.IdSort)
int index = ViewBag.ItemIndex ?? 0;
foreach (var contentPage in Model.ContentPages
    .Where(p => p.ParentReference == parentID)
    .OrderBy(p => p.SortOrder))
{
    <li style="padding-left: @(indent)px; color: red;">
        @Html.TextBoxFor(o => Model.ContentPages[index].Id)
        @contentPage.Title
        @Html.TextBoxFor(o => Model.ContentPages[index].SortOrder,
            new {@class = "sortBox"})
    </li>
    ViewBag.ItemIndex = ++index;
    @RenderItems(contentPage.Id, indent + 20)
    ;
    index = ViewBag.ItemIndex;
}
}
@using (Html.BeginForm("SortOrderMenu", "secure", Model.ContentPages, FormMethod.Post))
{
@RenderItems("ContentPages/6401")
<div class="activity-desk">
    <input type="submit" value="Spara ny sortering" class="btn btn-primary" name="saveSliders"    />
</div>
}

EDIT 2 ---------------

@helper RenderItems(string parentID, int indent = 0)
{
@Html.HiddenFor(o => Model.IdSort)
int index = ViewBag.ItemIndex ?? 0;
foreach (var contentPage in Model.ContentPages
                                 .Where(p => p.ParentReference == parentID)
                                 .OrderBy(p => p.SortOrder))
{
    <li style="padding-left: @(indent)px; color: red;">
        @Html.TextBoxFor(o => Model.ContentPages[index].Id)
        @contentPage.Title
        @Html.TextBoxFor(o => Model.ContentPages[index].SortOrder,
                                 new { @class = "sortBox" })
    </li>
    ViewBag.ItemIndex = ++index;
    @RenderItems(contentPage.Id, indent + 20);
                                           index = ViewBag.ItemIndex;
}
}
@using (Html.BeginForm("SortOrderMenu", "secure", Model.ContentPages, FormMethod.Post))
{
@RenderItems("/")
<div class="activity-desk">
    <input type="submit" value="Spara ny sortering" class="btn btn-primary" name="saveSliders" />
</div>
}

ControllerMethods:

[HttpGet]
    public ActionResult SortOrderMenu()
    {
        var allContentPages = RavenSession.Query<ContentPage>().ToList();
        var sortOrderModel = new SortOrderModel();
        sortOrderModel.ContentPages = allContentPages;

        return View(sortOrderModel);
    }
    [HttpPost]
    public ActionResult SortOrderMenu(SortOrderModel model)
    {
        foreach (var page in model.ContentPages)
        {
            var contPage = RavenSession.Load<ContentPage>(page.Id);
            contPage.SortOrder = page.SortOrder;
            RavenSession.SaveChanges();
        }
        return RedirectToAction("SortOrderMenu");
    }

使用for循环渲染树视图

最终会得到以下递归帮助器:

@helper RenderItems(string parentID, int indent = 0)
{
    foreach (var contentPage in Model.ContentPages
                                     .Where(p => p.ParentReference == parentID)
                                     .OrderBy(p => p.SortOrder))
    {
        var index = Model.ContentPages.IndexOf(contentPage);
        <li style="padding-left: @(indent)px; color: red;">
            @Html.TextBoxFor(o => Model.ContentPages[index].Id)
            @contentPage.Title
            @Html.TextBoxFor(o => Model.ContentPages[index].SortOrder,
                new { @class = "sortBox" })
        </li>
        @RenderItems(contentPage.Id, indent + 20)
    }
}

在你的视图中像这样调用它:

@RenderItems("/");

编辑:或者,您可以使用隐藏输入,并使用Model.ContentPages.Index作为名称来定义索引:

@helper  RenderItems(string parentID, int indent = 0)
{
    foreach (var contentPage in Model.ContentPages
                                     .Where(p => p.ParentReference == parentID)
                                     .OrderBy(p => p.SortOrder))
    {
        var index = Guid.NewGuid();
        <input type="hidden" name="Model.ContentPages.Index" value="@(index)" />
        <li style="padding-left: @(indent)px; color: red;">
            @contentPage.Title 
            <input type="text" class="sortBox" 
                   name="Model.ContentPages[@(index)].SortOrder" 
                   value="@contentPage.SortOrder" />
        </li>
        @RenderItems(contentPage.Id, indent + 20)
    }
}

更多细节见Phil Haack关于集合绑定的博文