【问题标题】:How to bind a selectlist with viewmodel?如何将选择列表与视图模型绑定?
【发布时间】:2011-07-08 19:56:47
【问题描述】:

我无法将选择列表绑定到我的 ViewModel。

我有一个 ViewModel,它包含一个 Question 实体和一个字符串

   public class QuestionViewModel
{
    public Question Question { get; set; }
    public string RefUrl { get; set; }

    public QuestionViewModel()
    {
    }

    public QuestionViewModel(Question question, string RefUrl)
    {
        this.Question = question;
        this.RefUrl = RefUrl;
    }

    public QuestionViewModel(Question question)
    {
        this.Question = question;
        this.RefUrl = "";
    }
}

这是控制器:

public ActionResult Edit(int id)
    {
        Question question = db.Question.Single(q => q.question_id == id);
        QuestionViewModel qvm = new QuestionViewModel(question);
        ViewBag.category_id = new SelectList(db.Category, "category_id", "category_name", qvm.Question.category_id);
        ViewBag.type_code = new SelectList(db.Question_Type, "type_code", "type_description", qvm.Question.type_code);
        return View(qvm);
    }

我认为的代码如下所示:

<div class="editor-label">
        @Html.LabelFor(model => model.Question.type_code, "Question_Type")
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(model => Model.Question.Question_Type, (SelectList)ViewBag.type_code)
        @Html.ValidationMessageFor(model => model.Question.type_code)
    </div>

视图确实将问题实体的 Question_Type 设置为所选值,但是当我提交表单时, ValidationMessageFor 触发器??

【问题讨论】:

  • Model.Question.Question_Type Model.Question.type_code 是 2 个不同的属性?您有 Question.type_code 的验证消息,但您正在设置 Question_Type?

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


【解决方案1】:

您拥有的是不是视图模型。这是一个混合类,您已将其称为视图模型,并且您已在其中包装了您的域实体 (Question)。这很糟糕,不要这样做。

这是我向您推荐的。首先设计一个真实的视图模型,它将反映您的视图要求(根据您当前的描述,它是一个下拉列表,包含一些问题类型并允许用户从此 ddl 中选择一些问题类型):

public class QuestionViewModel
{
    [DisplayName("Question_Type")]
    public string SelectedQuestionType { get; set; }

    public IEnumerable<SelectListItem> QuestionTypes { get; set; }

    // didn't see where you are using this on your view
    public string RefUrl { get; set; }
}

然后在域模型和视图模型之间映射控制器。当然,进一步的改进是使用AutoMapper 来避免在您的控制器操作中出现这种映射:

public ActionResult Edit(int id)
{
    var question = db.Question.Single(q => q.question_id == id);
    var qvm = new QuestionViewModel
    {
        // preselect a value
        SelectedQuestionType = question.type_code,
        QuestionTypes = db.Question_Type.Select(x => new SelectListItem
        {
            Value = x.type_code,
            Text = x.type_description
        })
    };
    return View(qvm);
}

然后:

<div class="editor-label">
    @Html.LabelFor(x => x.SelectedQuestionType)
</div>
<div class="editor-field">
    @Html.DropDownListFor(
        x => SelectedQuestionType, 
        new SelectList(Model.QuestionTypes, "Value", "Text")
    )
    @Html.ValidationMessageFor(x => x.SelectedQuestionType)
</div>

最后一句话:确保你已经摆脱了任何ViewBag/ViewData 丑陋,并将你的视图需要的任何东西放入视图模型中。您已经在控制器操作中显示了一些类别,这些类别没有在您显示的视图 sn-p 中具体化。如果您需要它们,只需将它们放在您的视图模型中,就像我们对问题类型所做的那样。

【讨论】:

  • 但是我需要将 Question 实体发送到 View 以便我可以编辑它?这样你只发送包含 Question_Type 和 ref_URL 的 QuestionViewModel
  • @Nanek,不,您不需要将任何问题实体发送到您的视图。正如我所说,您需要在视图中编辑的所有属性都必须是视图模型的一部分。然后,您的 Post 操作将采用相同的视图模型并将其映射回域 Question 模型,该模型将被发送到存储库以进行编辑或任何需要的操作。
  • @Darin,为什么 QuestionTypes 在帖子中为空? Post 方法会是什么样子?
  • @mcass20,它为空,因为&lt;select&gt; 元素在提交表单时仅将选定的值发送到服务器。这就是 HTML 的工作原理。在您的 POST 操作中,您可以从您在 GET 操作中执行的同一存储中填充 QuestionTypes 属性。
猜你喜欢
  • 2011-08-10
  • 2013-04-05
  • 2020-01-21
  • 1970-01-01
  • 2017-05-06
  • 1970-01-01
  • 2018-09-01
  • 1970-01-01
相关资源
最近更新 更多