MVC 3:编辑表单上的DropDownList,用于作为ViewModel属性的对象

时间:2013-03-20 12:23:54

标签: c# asp.net-mvc asp.net-mvc-3 razor entity-framework-4

概述: 我正在尝试使用具有属性的ViewModel,该属性是我正在尝试编辑的模型类。在直接编辑模型时,我已经看到编辑表单使用MVC脚手架编辑表单,但是我尝试使用包含正在编辑的模型的ViewModel。除了保存DropDownList中显示的字段外,一切都有效。

说明: 我试图使用MVC 3的脚手架功能为模型创建编辑表单。 在MVC音乐商店教程中,这是针对AlbumStoreManagerController的编辑页面完成的。 在该页面中,他们为Genre和Artist提供了两个下拉菜单。在视图中每个看起来都类似于: -

<div class="editor-label">
    @Html.LabelFor(model => model.GenreId, "Genre")
</div>
<div class="editor-field">
    @Html.DropDownList("GenreId", String.Empty)
    @Html.ValidationMessageFor(model => model.GenreId)
</div>

据我所知,这些可以使用ViewBag在控制器中填写选项。

ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);

直接使用模型

在我的代码中,我设法对通过实体框架保存到数据库的对象做了同样的事情。

模型

public class Season
{
    public int SeasonId { get; set; }
    public int ClubId { get; set; }
    public Club Club { get; set; }
}

控制器中的代码

ViewBag.ClubId = new SelectList(clubs, "ClubId", "Name", season.ClubId);

查看

<div class="editor-label">
    @Html.LabelFor(model => model.ClubId, "Club")
</div>
<div class="editor-field">
    @Html.DropDownList("ClubId", String.Empty)
    @Html.ValidationMessageFor(model => model.ClubId)
</div>

这很好用。

使用视图模型

但是现在我已经意识到页面需要的文本比我正在编辑的模型中显示的文本要多。 我希望创建一个特殊的视图模型,包括已编辑的模型(季节)和我想要显示的额外文本。

视图模型

public class EditSeasonViewModel
{
    public string PlayerName {get; set;}
    public string SummaryText {get; set;}
    public int PlayerId {get; set;}
    public Season season {get; set;}
}

我这样做了,更改控制器让HttpGet和HttpPost方法使用新的ViewModel,更改了View以接受新的ViewModel,并更改了视图中的所有'EditorFor'方法以使用model.season.MyProperty。

控制器中的代码

ViewBag.ClubId = new SelectList(clubs, "ClubId", "Name", seasonVM.season.ClubId);

视图中的代码

<div class="editor-label">
    @Html.LabelFor(model => model.season.ClubId, "Club")
</div>
<div class="editor-field">
    @Html.DropDownList("ClubId", String.Empty)
    @Html.ValidationMessageFor(model => model.season.ClubId)
</div>

调试HttpPost方法时,季节的所有值都正确存在,但应该来自DropDropList的ClubId值除外。

我没有直接更改View中的DropDownList,就像我们直接使用Model时一样。

问题: 我的问题是,在使用新EditSeasonViewModel时,我需要更改哪些内容才能正确保存ClubId?

另外,控制器中HttpGet方法中的ViewBag.ClubId如何与View中的DropDownList匹配,然后将其值传递回HttpPost方法?

3 个答案:

答案 0 :(得分:11)

这是你的DropDownList声明不正确。试试这个:

@Html.DropDownListFor(m => m.season.ClubId, ViewBag.ClubId)

真的,您应该在模型中添加选择列表:

public SelectList Clubs { get; set; }

然后在控制器中填充它:

Model.Clubs = new SelectList(clubs, "ClubId", "Name", season.ClubId);

然后你可以这样做:

@Html.DropDownListFor(m => m.season.ClubId, Model.Clubs)

答案 1 :(得分:3)

避免使用ViewBag / ViewData 等动态内容将数据从操作方法传输到视图。切换到强类型方法。

更新您的Viewmodel以再增加2个属性。一个可以举办一系列可用的俱乐部,一个可以举办选定的俱乐部。

public class EditSeasonViewModel
{
    public List<SelectListItem> Clubs { set;get;}
    public int SelectedClub { set;get;}

    public string PlayerName {get; set;}
    public string SummaryText {get; set;}
    public int PlayerId {get; set;}
    public Season season {get; set;}

    public EditSeasonViewModel()
    {
        Clubs=new List<SelectListItem>();
    }
}

现在,在您的GET操作中,获取分会并将其加载到Clubs属性。

public ActionResult create(int id)
{
  var vm=new EditSeasonViewModel();
  vm.Clubs=GetListOfSelectListItemFromClubsFromSomeWhere();
  return View(vm);
}

假设GetListOfSelectListItemFromClubsFromSomeWhere是一个为您的俱乐部返回SelectListItem列表的方法

public List<SelectListItem> GetListOfSelectListItemFromClubsFromSomeWhere()
{
  // to do : return List<SelectListItem> with Value and Text(ClubId Id & Name)
}

并在您的视图中,使用Html.DropDownListFor辅助方法

@model EditSeasonViewModel
@using(Html.Beginform())
{

  @Html.DropdownlistFor(x=>x.SelectedClub,
                          new SelectList(Model.Clubs,"Value","Text"),"select")
  <input type="submit" />
}

发布此表单时,您将在已发布模型的SelectedClub属性中获取所选俱乐部的ID。

[HttpPost]
public ACtionResult Create(EditSeasonViewModel model)
{
  if(ModelState.IsValid)
  {
   int clubId= model.SelectedClub;
   //to do : save and redirect (PRG pattern)
  }
  vm.Clubs=GetListOfSelectListItemFromClubsFromSomeWhere();
  return View(model);
}

答案 2 :(得分:0)

请确保在您的编辑/创建操作控制器中,属性已正确绑定:

public async Task<ActionResult> Edit([Bind(Include = "SeasonId,ClubId, otherproperties"]){
// code ...
}