2014-09-13 88 views
0

我有一个动态填充的问题和答案列表。动态MVC RadioButton组选择的答案

两个问题:

  1. 的问题和答案回发后不显示
  2. 所选择的答案是缺少

视图模型

public class RegistrationViewModel : RegisterExternalLoginModel 
{ 
    //...etc... 
    public Question Question { get; set; } 
    public Answer Answer { get; set; } 
    public List<Question> Questions { get; set; } 
    public IList<Answer> PossibleAnswers { get; set; } 
    public List<SelectedAnswer> SelectedAnswers { get; set; } 
    public IList<SelectedAnswer> PreviousAnswers 
    { 
     set 
     { 
      foreach(Question q in Questions) 
      { 
       q.SelectedAnswers = value.Where(t => t.questionId == q.objectId).ToList() ; 
      } 
     } 
    } 
} 

所选答案WER

public Answer SelectedAnswer 
    { 
     get 
     { 
      if (SelectedAnswers != null && SelectedAnswers.Count > 0) 
      { 
       var answers = SelectedAnswers.Where(t => t.questionId == objectId); 
       if (answers.Count() == 1) 
       { 
        var result = Answers.Where(t => t.objectId == answers.First().answerId).First(); 
        return result; 
       } 
      } 
      return null; 
     } 
    } 

的ActionResult

public ActionResult CreateQuestions() 
    { 
     RegistrationViewModel vm = new RegistrationViewModel(); 
     IQFacade facade = new QFacade(CreateUserContext(true)); 

     //Questions and Answers 
     vm.Questions = facade.GetQuestions().ToList(); 
     vm.PossibleAnswers = facade.GetPossibleAnswers(); 

     return View(vm); 

    } 

[HttpPost] 
public ActionResult CreateQuestions(RegistrationViewModel vm) 
    { 
     var context = CreateUserContext(true); 

      try{ 
       IQFacade f = new QFacade(context); 
       f.CreateSomething(vm.User.name, vm.etc, vm.SelectedAnswers);//Need all the answers here, but null 
      } 
      catch (Exception ex) 
      { 
       //error stuff, etc... 
       return View(vm);//the questions do not appear after this point. Do I need to bind them again from GetQuestions or shouldn't they still be a part of the vm object that I am returning? 
      } 
     } 

     return RedirectToAction("Index"); 
    } 

在视图中,我使用的编辑器模板

@Html.EditorFor(x => x.Questions) 

模板

@foreach (var possibleAnswer in Model.Answers) 
{ 
    <div class="radio"> 
     @Html.RadioButtonFor(question => question.SelectedAnswer, possibleAnswer.objectId, new { id = possibleAnswer.objectId }) 

     <label for="@possibleAnswer.objectId">@possibleAnswer.text <span>@possibleAnswer.value</span></label> <p>@possibleAnswer.description</p> 
    </div> 
} 

一切工作的第一次,但不是回发后。我已阅读了几十个类似的SO帖子。我错过了什么?

+0

1.你的财产'SelectedAnswer'没有一个setter。 2.你试图绑定到一个复杂的属性('Answer'),但单选按钮组只回发一个单一的值。你应该有'public int SelectedAnswer {get;组; }'。 – 2014-09-13 04:01:58

+0

这个问题呢?我是否需要在错误捕获中创建另一个数据库调用GetQuestions(),或者是否应该在发布后将其保留填充? – User970008 2014-09-14 12:09:49

+0

很多你在这里做的事情都令人困惑,例如你有一个'SelectedAnswers'集合 - 每个问题可以有多个答案吗?你也应该有简单的getter和setter来查看模型属性并将它们填充到控制器中,而不是在getter中。由于您似乎没有为这些问题渲染任何输入控件,因此他们不会被回发,并且您将需要再次获取它们(但是,这可能会更好地表现出明智的效果,而不是回馈大量额外的输入,以防万一 – 2014-09-14 12:44:06

回答

1

根据意见,你的模型应该是这样的(不知道你的所有模特属性的,所以我在这里做一些假设)

public class QuestionVM 
{ 
    public int ID { get; set; } // for binding 
    public string Text { get; set; } 
    [Required] 
    public int? SelectedAnswer { get; set; } // for binding 
    public IEnumerable<Answer> PossibleAnswers { get; set; } 
} 

public class RegistrationViewModel : RegisterExternalLoginModel 
{ 
    public RegistrationViewModel() 
    { 
    Questions = new List<QuestionVM>(); 
    } 
    //...etc... 
    public List<QuestionVM> Questions { get; set; } 
} 

GET方法

public ActionResult CreateQuestions() 
{ 
    RegistrationViewModel vm = new RegistrationViewModel(); 
    ..... 
    // Populate the questions and answers 
    var questions = facade.GetQuestions().ToList(); 
    var answers = facade.GetPossibleAnswers(); 
    foreach (var question in questions) 
    { 
     QuestionVM qvm = new QuestionVM(); 
     qvm.ID = question.ID; 
     qvm.Test = question.Text; 
     // Add possible answers for the question 
     qvm.PossibleAnswers = answers.Where(a => a.QuestionID == question.ID); 
     // If loading existing questions/answers for existing user, also set value of current SelectedAnswer so its selected by default in the view 
     vm.Questions.Add(qvm); 
    } 
    return View(vm); 
} 

查看

@model YourAssembly.RegistrationViewModel 
.... 

@for(int i = 0; i < Model.Questions.Count; i++) 
{ 
    @Html.HiddenFor(m > m.Questions[i].ID) // for binding 
    @Html.DisplayFor(m > m.Questions[i].Text) 
    foreach(var answer in Model.Questions[i].PossibleAnswers) 
    { 
    @Html.RadioButtonFor(m => m.Questions[i].SelectedAnswer, answer.ID, new { id = answer.ID}) 
    <label for="@answer.ID">answer.Text</label> 
    } 
} 

POST方法

[HttpPost] 
public ActionResult CreateQuestions(RegistrationViewModel vm) 
{ 
    if (!ModelState.IsValid) 
    { 
    // You need to rebuild the question text and possible answers because these are not posted back 
    return View(vm); 
    } 
    // Your model is now populated with the ID of each question and the selected answer which can be saved to the database 

请注意,您可以为问题和答案文本值添加隐藏输入,以便回发,但一般而言,其更好的性能可以重新加载到控制器中(如果包含正确的数据注释并包含客户端验证,模型应该反正总是有效的)

+0

谢谢,我不得不修改一些东西,因为SelectedAnswers和Questions是从自动生成的EF实体填充的。但我得到了它的工作。 – User970008 2014-09-15 02:21:41