【问题标题】:Model Containing List of Models (MVC-3, Razor)模型包含模型列表(MVC-3,Razor)
【发布时间】:2011-06-10 20:34:51
【问题描述】:

这个问题已经困扰我两天了。有一些类似的帖子,但没有一个可以完全解决我的问题。

使用 MVC-3,Razor 语法:

-- EDIT.cshtml--

@using (Html.BeginForm("Edit", "My", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <!-- Some fields... -->
    <div class="editor-field">
        @Html.TextAreaFor(m => m.LongDescription)
        @Html.ValidationMessageFor(m => m.LongDescription)
    </div>

    <!-- Some more fields work... Including picture upload (summary).-->
    <input name="button" type="submit" value="Add Picture" />

    <!-- Picture Item display -->
    @foreach(var thumbnail in Model.ThumbnailImagePathAndNames) 
    {
      <img src="@Url.Content(@thumbnail.ThumbnailPicturePath)" alt="" width="200" />
      @Html.RadioButtonFor(o=>o.SelectedImage, @thumbnail.ImageGUID)  Primary Picture 
      <!-- Checkbox to mark for deletion -->
      @Html.CheckBoxFor(o=>thumbnail.Delete) Delete ???????? <!---- Here is a problem - I don't understand how this should work -->
    }
    <input id="Submit1" name="button" type="submit" value="Complete Edit!" />
}

-- MyController.cs --

 [HttpPost]
 public ActionResult Edit(String button, HttpPostedFileBase file, MyMainModel model)
 {
     // if button = submit picture,  work with picture here and break(long story)

     // save model data
         // if valid, save and redirect


     // not valid or error, load up view like normal but with error messages
     model.LoadThumbnails();
     return View(model);

 }

-- MyMainModel.cs --

public class MyMainModel
{
    // some properties...
     public Guid? SelectedImage { get; set; }

    [Display(Name = "Detailed Description")]
    public String LongDescription { get; set; }

    // some more properties....


    // and finally my list of models
    public IList<ThumbnailModel> ThumbnailImagePathAndNames { get; set; }

    public void LoadThumbnails()
    {
         // load up initial thumbnail models
         this.ThumbnailImagePathAndNames = new List<ThumbnailModel>(readDataService.GetThumbnailModels(this.SomeID));
    }
}

-- ThumbnailModels.cs --

public class ThumbnailModel
{
    public Guid ImageGUID { get; set; }
    public String FullSizePicturePath { get; set; }
    public String ThumbnailPicturePath { get; set; }

    public bool Delete { get; set; }
}

那么问题是什么?好吧,当“完成编辑!”按下按钮,调用 MyController 的 Edit,正如预期的那样,MyMainModle 的所有数据都完好无损......除了 ThumbnailModel 的列表 - 那些结果为空。

这应该怎么做?我已经尝试了许多不同的方法,包括制作一个可编辑的模板和使用 EditFor(o=>... 都无济于事(这变得令人困惑,因为我不知道 EditFor 是应该用于整个集合还是只是集合中的单个项目 - 我尝试了两种方法)。所有这些都可以正常工作,直到我添加了删除复选框的复杂性,因此需要检索 ThumbnailModels 列表以检查该内部 Delete 属性值。

感谢大家阅读并尝试理解这一点。

[免责声明 - 一些变量和方法名称已被更改以保护无辜程序。很多代码已经被剥离并被注释代码取代。]

【问题讨论】:

  • 不应该是thumbnail=&gt;thumbnail.Delete吗?

标签: model asp.net-mvc-3 razor


【解决方案1】:

这是我用来说明一些概念的示例:

型号:

public class MyMainModel
{
    public Guid? SelectedImage { get; set; }
    public string LongDescription { get; set; }

    public IEnumerable<ThumbnailModel> ThumbnailImagePathAndNames { get; set; }

    public HttpPostedFileBase File { get; set; }
}

public class ThumbnailModel
{
    public Guid ImageGUID { get; set; }
    public bool Delete { get; set; }
}

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyMainModel
        {
            // TODO: fetch from the repository instead of hardcoding
            ThumbnailImagePathAndNames = new[] 
            {
                new ThumbnailModel { ImageGUID = Guid.NewGuid() },
                new ThumbnailModel { ImageGUID = Guid.NewGuid() },
                new ThumbnailModel { ImageGUID = Guid.NewGuid() },
            }
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyMainModel model) 
    {
        ... the model will be properly bound here
    }
}

查看:

@model AppName.Models.MyMainModel
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
@using (Html.BeginForm("index", "home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <div class="editor-field">
        @Html.TextAreaFor(m => m.LongDescription)
        @Html.ValidationMessageFor(m => m.LongDescription)
    </div>
    <input type="file" name="file" />
    <!-- Use different names for the upload and complete submit
         buttons so that you can distinguish which one was clicked
         in the POST action 
    -->
    <input name="upload" type="submit" value="Add Picture" />

    @Html.EditorFor(x => x.ThumbnailImagePathAndNames)    
    <input name="complete" type="submit" value="Complete Edit!" />
}

编辑器模板:(~/Views/Home/EditorTemplates/ThumbnailModel.cshtml):

@model AppName.Models.ThumbnailModel
<!-- Pass the image id as hidden field -->
@Html.HiddenFor(x => x.ImageGUID)
@Html.CheckBoxFor(x => x.Delete)

【讨论】:

  • 太棒了!有用!!非常感谢 - 这非常有帮助。我试图处理这个示例的最后一件事是,我对每个 ThumbnailModel 都有一个更复杂的布局。在我的原始代码中,我使用@foreach(Model.ThumbnailImagePathAndNames 中的var thumbnail)之类的东西......似乎我不能将我的布局(列限制的东西)代码放在编辑周围,然后使用@Html.EditorFor (x => 缩略图)。你知道我怎样才能得到这种细粒度的控制吗?在模板中以某种方式将 @model IEnumerable 放在顶部?谢谢!
  • ** 我可能不得不将上述问题移至新线程。换句话说,我希望对@Html.EditorFor 有更多的控制,使用我自己的@Foreach 分别处理每个模型,而不是让.NET 循环并自动呈现它。将编辑器模板更改为采用 @model IEnumerable 并在其中实现 @foreach 已被证明是不成功的。
  • @Rob,我不明白你需要什么样的控制。在您的示例中,您只是遍历集合,并且为每个元素输出几个输入字段。 EditorFor 应该足以避免您编写所有这些内容。
  • 嗨达林,最初(代码被剥离以简化示例),我一直在跟踪列和行计数,并根据我在@Foreach 中的行和列更改 DIV 样式。但是,我发现这不是最好的解决方案,并决定对 DIV 采取稍微不同的方法。现在我的格式与您在上面概述的 @Html.EditorFor(x => x.ThumbnailImagePathAndNames) 一样工作......因此,我的代码更清晰,更容易理解。再次感谢您花时间解释这一点!
  • 干净的代码总是有助于解决与原始问题相似的问题。谢谢@DarinDimitrov
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-27
  • 2016-11-23
  • 1970-01-01
  • 2012-08-22
  • 2012-04-02
  • 1970-01-01
相关资源
最近更新 更多