【问题标题】:Render a treeview using a for-loop使用 for 循环渲染树视图
【发布时间】:2014-07-10 16:33:39
【问题描述】:

我正在上这门课:

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 的列表,其值:

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

编辑!

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

控制器方法:

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

【问题讨论】:

  • 请先放置您的尝试示例。
  • 添加了一个我现在尝试的示例,@Cubicle.Jockey

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


【解决方案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

【讨论】:

  • 谢谢!很棒的工作!它呈现完美。 =) 但是我将如何在 html.beginform 中使用它来将其发布到 [httpPost] 方法。因为我的目标是能够更新 SortOrder-values
  • 再次感谢!但是我发现了一些不匹配的东西。在文本框中写出的 sortOrder-values 与其数据不匹配。我该如何解决这个问题?
  • 我在 html.beginform 中尝试过,但传递给 [httppost]-metod 的值不正确。从我创建的示例代码的示例中,它仅将带有父引用“ContentPages/1”的内容页面列表发布到 [httppost] 方法。请帮帮我=)
  • 哦,我明白了。只是改变了IndexOf方法计算item索引的逻辑。请注意,第二种(替代)方式也应该有效。
  • 我添加了 var index = Model.ContentPages.IndexOf(contentPage);并使用 ViewBag.ItemIndex 删除所有内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-30
  • 2016-04-10
  • 1970-01-01
  • 2012-07-13
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
相关资源
最近更新 更多