You can create a editor template and pass the control list as model to the template and in the template you can iterate that list to generate the control. As i have shown below.
1->Create a class for Control Information.
public class ControlInfo
{
public string ControlType { get; set; }
public string ControlID { get; set; }
public string ControlName { get; set; }
public string ControlValue { get; set; }
public string ControlLabel { get; set; }
public bool IsChecked { get; set; }
}
2->Create an Editor Template (Partial view with control name say CustomControl.cshtml) in \Views\Shared\EditorTemplates path.
@model List<MvcApplication2.Models.ControlInfo>
<table>
@foreach (MvcApplication2.Models.ControlInfo ControlInfo in Model)
{
<tr>
<td>@ControlInfo.ControlLabel</td>
<td>
@switch (ControlInfo.ControlType.ToLower())
{
case "textbox":
<input type="text" name="@ControlInfo.ControlName" id="@ControlInfo.ControlID" value="@ControlInfo.ControlValue" />
break;
case "checkbox":
if (ControlInfo.IsChecked)
{
<input type="checkbox" name="@ControlInfo.ControlName" id="@ControlInfo.ControlID" value="@ControlInfo.ControlValue" checked="checked" />
}
else
{
<input type="checkbox" name="@ControlInfo.ControlName" id="@ControlInfo.ControlID" value="@ControlInfo.ControlValue" checked="checked" />
}
break;
default:
break;
}
</td>
</tr>
}
</table>
3->Create a model for main view (say HomeModel).
public class HomeModel
{
public List<ControlInfo> ControlList { get; set; }
public void PolulateControlList()
{
//You can fill this list from database.
// For example i have filled the list manually.
ControlList = new List<ControlInfo>();
ControlList.Add(new ControlInfo() {ControlType="TextBox",ControlName="tbox1", ControlID="tbox1", ControlLabel="Name", ControlValue="Martin" });
ControlList.Add(new ControlInfo() { ControlType = "CheckBox", ControlName = "cbox1", ControlID = "cbox1", ControlLabel="Is Correct", ControlValue = "Yes", IsChecked=true });
}
}
4->Consume the editor template in the main view as.
@model MvcApplication2.Models.HomeModel
@{
ViewBag.Title = "Home Page";
}
@Html.EditorFor(model=>model.ControlList,"CustomControl")
5-> Call the main view in the controller ( Index here).
public ActionResult Index()
{
HomeModel ModelObj = new HomeModel();
ModelObj.PolulateControlList();
return View(ModelObj);
}
Edit 1:
For getting the posted value you need to modify the Editor Templates as below. The model properties whose name is equal to the name of the control posted as name value collection , will get automatically binded by the model binder of the mvc frame work, so for each property in the control collection i have created hidden tags and one input tag for the input value.
@model List<MvcApplication2.Models.ControlInfo>
<table>
@{ var index = -1;}
@foreach (MvcApplication2.Models.ControlInfo ControlInfo in Model)
{
index++;
<tr>
<td>@ControlInfo.ControlLabel</td>
<td>
<input type="hidden" name="@("ControlList[" + index + "].ControlID")" value="@ControlInfo.ControlID" />
<input type="hidden" name="@("ControlList[" + index + "].ControlLabel")" value="@ControlInfo.ControlLabel" />
<input type="hidden" name="@("ControlList[" + index + "].ControlName")" value="@ControlInfo.ControlName" />
<input type="hidden" name="@("ControlList[" + index + "].ControlType")" value="@ControlInfo.ControlType" />
@switch (ControlInfo.ControlType.ToLower())
{
case "textbox":
<input type="text" name="@("ControlList["+index+"].ControlValue")" id="@ControlInfo.ControlID" value="@ControlInfo.ControlValue" />
break;
case "checkbox":
<input type="hidden" name="@("ControlList[" + index + "].ControlValue")" value="@ControlInfo.ControlValue" />
if (ControlInfo.IsChecked)
{
<input type="checkbox" name="@("ControlList[" + index + "].IsChecked")" id="@ControlInfo.ControlID" value="true" checked="checked" />
}
else
{
<input type="checkbox" name="@("ControlList[" + index + "].IsChecked")" id="@ControlInfo.ControlID" value="true" />
}
break;
default:
break;
}
</td>
</tr>
}
</table>
And in the main view you need to have form
@model MvcApplication2.Models.HomeModel
@{
ViewBag.Title = "Home Page";
}
@using(Html.BeginForm()){
@Html.EditorFor(model=>model.ControlList,"CustomControl")
<input type="submit" name="name" value="Submit" />
}
And in controller you need to have corresponding post method
[HttpPost]
public ActionResult Index(HomeModel ModelObj)
{
// Your logic..........
return View(ModelObj);
}
This ModelObj will have the posted values.
MultipleChoiceQuestion : Question), so your controller nor your view don't have to know anything about what kind of question they're returning or rendering. This way the template will render the question in the proper way.