使用for循环渲染树视图

时间:2014-05-21 20:34:29

标签: c# asp.net-mvc for-loop

我有这堂课:

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

具有listpropery的上述类是此类的列表:

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发送到视图。

在视图中:Model.ContentPages是一个包含5个ContentPage的List,其值为:

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.TextBoxFor的视图中使用它来获取SortOrder-Properties,这样我就可以更改每个对象的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

EDIT!

@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>
}

编辑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");
    }

1 个答案:

答案 0 :(得分:1)

你最终会得到以下递归助手:

@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)
    }
}

More details about it in Phil Haack's great blog post about collection binding