基于相关数据构建编辑视图模型

本文关键字:视图 模型 编辑 构建 于相关 数据 | 更新日期: 2023-09-27 18:17:05

我有一个应用程序来创建和编辑调查。每个调查都包含一组问题和相关的回答(答案)。创建调查时,将从单独的Questions表生成问题集。每年,我们都会为每个用户创建一份带有相同问题集的新调查,以便随着时间的推移对回复进行比较。

创建调查时,保存每个问题的答案,但是用户可能没有对每个问题给出答复,现在我必须构建一个视图来编辑现有的答复。

模型
public class Survey
{
    public int ID { get; set; }
    public int AreaID { get; set; }
    public Status Status { get; set; }
    public DateTime AssessmentDate { get; set; }
    public virtual Area Area { get; set; }
    public virtual ICollection<Answer> Answers { get; set; }
}
public class Question
{
    public int ID { get; set; }
    public string QuestionText { get; set; }
    public virtual ICollection<Answer> Answers { get; set; }
}
public class Answer
{
    public int ID { get; set; }
    public int? Response { get; set; }
    public int QuestionID { get; set; }
    public int SurveyID { get; set; }
    public virtual Question Question { get; set; }
    public virtual Survey Survey{ get; set; }
}

这是我的视图模型,我用它来创建编辑屏幕的视图

public class SurveyResponseViewModel
{
    public Assessment Assessment { get; set; }
    public IEnumerable<Question> Questions { get; set; }
}

, GET方法中的代码是

public ActionResult Edit(int? id) 
{ 
    if (id == null) 
    { 
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
    } 
    Survey survey = db.Surveys.Find(id); 
    var viewModel = new SurveyResponseViewModel 
    { 
        Survey = survey, 
        Areas = new SelectList(db.Areas, "ID", "SubLevel").ToList(), 
        Questions = db.Questions.Where(q => q.isActive) 
    }; 
    if (survey == null) 
    { 
        return HttpNotFound(); 
    } 
    return View(viewModel); 
}

这将用所有问题填充我的视图模型,但是每个问题包含一个答案集合。如何在视图中仅显示和编辑与此调查相关的每个问题的答案?

@foreach (var question in Model.Questions)
{
    // Display the question
    @Html.Raw(question.QuestionText)
    // How to create an input for the associated response??
    <input  type="text" name="????" placeholder="Enter a number..." value="????" />
}

注意响应是int?,并且可以在05之间取值(如果用户尚未给出响应,则可以在null之间取值)。理想情况下,我希望它被渲染为一个单选按钮来选择可能的值。

基于相关数据构建编辑视图模型

首先,您需要创建一个表示问题及其答案的视图模型

public class QuestionVM
{
    public int QuestionID { get; set; }
    public string QuestionText { get; set; }
    public int? AnswerID { get; set; }
    [Range(0, 5)]
    public int? Response { get; set; }
}

和主视图模型将是(注意,视图模型在编辑时不应该包含作为数据模型的属性)

public class SurveyResponseVM
{
    public int ID { get; set; } // this will be bound by the route value
    [Required(ErrorMessage = "Please select an area")]
    [Display(Name = "Area")]
    public int? SelectedArea { get; set; }
    public IEnumerable<SelectListItem> AreaList { get; set; }
    .... // other properties of assessment that you need for the view
    public List<QuestionVM> Questions { get; set; }
}

以便在视图中使用

@model SurveyResponseVM
....
@using (Html.BeginForm())
{
    @Html.DropDownListFor(m => m.SelectedArea, Model.AreaList)
    ....
    for(int i = 0; i < Model.Questions.Count; i++)
    {
        <h3>@Model.Questions[i].QuestionText</h3>
        @Html.HiddenFor(m => m.Questions[i].AnswerID)
        for (int j = 0; j < 6; j++)
        {
            <label>
                @Html.RadioButtonFor(m => m.Questions[i].Resonse, j, new { id = "" })
                <span>@j</span>
            </label>
        }
    }
    <input type="submit" value="Save" />
}

将返回到

public ActionResult Edit(SurveyResponseVM model)

为了在GET方法中获取值,您的第二个查询(db.Questions.Where(q => q.isActive))似乎没有必要,因为您已经有了与Survey相关联的Answer集合(并且每个Answer包含Question属性)。你的代码可以是

Survey survey = db.Surveys.Find(id);
if (survey == null) // check for null here
{ 
    return HttpNotFound(); 
} 
IEnumerable<Area> areas = db.Areas;
SurveyResponseVM model = new SurveyResponseVM()
{
    ID = survey.ID,
    SelectedArea = survey.AreaID,
    .... // other properties of Survey as required for the view
    AreaList = new SelectList(areas , "ID", "SubLevel"),
    Questions = survey.Answers.Select(x => new QuestionVM() 
    {
        QuestionText = x.Question.QuestionText, 
        AnswerID = x.ID, 
        Response = x.Response 
    }) 
};
return View(model);