无法将两个模型合并到一个ViewModel中

本文关键字:一个 ViewModel 合并 两个 模型 | 更新日期: 2023-09-27 18:25:48

我一直试图使用ViewModels将两个模型显示在一个视图中,但失败了。

我现在有一个简单的视图,有3个字段(Comment、Name、Department)和一个匹配的模型。我有一个控制器,它返回一个空视图,当你提交表单时,空模型会被填充并传递回控制器。我现在想把department字段变成一个下拉列表,并推断(可能不正确?)我应该创建另一个包含静态值的模型,然后通过控制器将ViewModel传递给视图,但当我尝试这样做时,它失败了:

视图:

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    <div class="fieldset">
        <fieldset>
            <legend>CommentDb</legend>
            <div class="editor-label">
                @Html.LabelFor(model => model.Comment)
            </div>
            <div>
                @Html.TextAreaFor(model => model.Comment, new {style = "width: 900px; height:200px;", autocomplete = "off" })
                @Html.ValidationMessageFor(model => model.Comment)
            </div>
            <div class="editor-label">
                @Html.Label("Your Name")
                @*@Html.LabelFor(model => model.CommentByName)*@
                @Html.TextBoxFor(model => model.CommentByName, new { autocomplete = "off", placeholder = "Optional" } )
                @Html.ValidationMessageFor(model => model.CommentByName)
            </div>
            <div class="editor-label">
                @Html.Label("Your Department", new { @class = "display-label" })
                @*@Html.LabelFor(model => model.Department)*@
                @Html.TextBoxFor(model => model.Department, new { autocomplete = "off", placeholder = "Optional" })
                @Html.ValidationMessageFor(model => model.Department)
            </div>
        </fieldset>
        <br />
        <br />
    </div>
    <div>
        <input type="submit" value="Create" id="submit"/>
    </div>
}

部门下拉模型:

namespace SuggestionBox.Models
{
    public class DropDownModel
    {
        public String Departments { get; set; }
        public String SetDropDownList()
        {
            Departments = "Engineering";
            return Departments;
        }
    }
}

数据库模型:

namespace SuggestionBox.Models
{
    public class CommentModel
    {
        [Key]
        public int CommentiD { get; set; }
        public string CommentByName { get; set; }
        public string Department { get; set; }
        [Required]
        public string Comment { get; set; }
        public DateTime InsertDate { get; set; }
    }
}
namespace SuggestionBox.Models
{
    public class CommentDbContext : DbContext
    {
        public CommentDbContext() : base()
        {
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<CommentDbContext, SuggestionBox.Migrations.Configuration>());
        }
        public DbSet<CommentModel> Comments { get; set; }
    }
}

我尝试的ViewModel:

namespace SuggestionBox.ViewModels
{
    public class SuggestionBoxViewModel
    {
        public CommentModel Comments { get; set; }
        public DropDownModel Departments { get; set; }
        public SuggestionBoxViewModel()
        {
            Departments = new DropDownModel();
            Departments.SetDropDownList();
            Comments = new CommentModel();
        }
    }
}

控制器:

    public ViewResult Index()
    {
        SuggestionBoxViewModel vm = new SuggestionBoxViewModel();
        return View(vm);
    }

return View(vm);中,IDE表示:Argument类型"SuggestionBox.ViewModels.SuggestionBoxViewModel"不可分配给模型类型"SuugestionBox.Models.CommentModel"

知道我在这里做错了什么吗?

干杯。

无法将两个模型合并到一个ViewModel中

您正在将一项简单的任务变成过于复杂的任务。视图模型应仅包含视图中使用的属性,而不应包含方法。填充视图模型属性是控制器的责任。

查看型号

public class CommentModelVM
{
  [Required]
  public string Comment { get; set; }
  public string CommentByName { get; set; }
  [Display(Name="Your Department")] // add attributes associated with the view
  public string Department { get; set; }
  public SelectList DepartmentList { get; set } // to populate the dropdown options
}

控制器

public ActionResult Create()
{
    CommentModelVM model = new CommentModelVM();
    ConfigureViewModel(model);
    return View(model);
}
public ActionResult Create(CommentModelVM model)
{
  if (!ModelState.IsValid())
  {
    // Repopulate options and return view
    ConfigureViewModel(model);
    return View(model);
  }
  // Save and redirect
}
private void ConfigureViewModel(CommentModelVM model)
{
  List<string> departments = // create your list of departments here (from database or static list)
  model.DepartmentList = new SelectList(departments);
}

查看

....
@Html.LabelFor(m => m.Department)    
@Html.DropDownListFor(m => m.Department, Model.DepartmentList)
....

我只想首先说,通常情况下,将ViewModels的属性或类命名为它们绑定的视图控件是个坏主意。例如:DropDownModel。这样做会造成混乱,因为Models和ViewModels不表示UI组件,它们表示视图用于呈现其UI控件的实体和数据。

既然这么说是为了回答你的问题,我认为没有必要用ViewModel类来表示下拉列表中的静态部门列表。我认为您应该向SuggestionBoxViewModel类添加一个新的部门列表,如下所示:

namespace SuggestionBox.ViewModels
{
    public class SuggestionBoxViewModel
    {
        public CommentModel Comments { get; set; }
        public IEnumerable<string> Departments { get; set; }
        public string SelectedDepartment { get; set; }
        public SuggestionBoxViewModel()
        {
            Departments = new [] {"Engineering","Sales"};
            Comments = new CommentModel();
        }
        public int CommentiD 
        { 
            get { return Comments.CommentiD; }
        }
        public string CommentByName 
        { 
            get { return Comments.CommentByName; }
        }        
    }
}

然后在您的视图中,您所要做的就是将下拉列表绑定到部门列表。像这样:

在您的视图顶部:

@model SuggestionBox.ViewModels.SuggestionBoxViewModel

然后在您希望显示下拉列表的位置:

@Html.DropDownListFor(m => m.SelectedDepartment, new SelectList(Model.Departments))

就这样!我希望这能有所帮助。

您的视图似乎需要一个注释模型。

如果要绑定到ViewModel,则必须实现Comment公开的所有属性。

所以你的ViewModel可能看起来像这样:

namespace SuggestionBox.ViewModels
{
    public class SuggestionBoxViewModel
    {
        public CommentModel Comments { get; set; }
        public DropDownModel Departments { get; set; }
        public SuggestionBoxViewModel()
        {
            Departments = new DropDownModel();
            Departments.SetDropDownList();
            Comments = new CommentModel();
        }
        public int CommentiD 
        { 
            get { return Comments.CommentiD; }
        }
        public string CommentByName 
        { 
            get { return Comments.CommentByName; }
        }
        ...etc.
    }
}