asp.net-mvc – 如何在MVC 3中基于XML文件动态创建控件

前端之家收集整理的这篇文章主要介绍了asp.net-mvc – 如何在MVC 3中基于XML文件动态创建控件前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个XML文件存储在数据库中作为XML格式,其中包含一些控件,如下拉文本框,标签文本区域等,可能有或没有初始值。所以我的目标是读取XML文件,并基于控件类型,我需要动态创建该控件,并关联初始值(如果有)和页面的预览必须在视图中显示。任何人都请帮助我如何在MVC 3中为这种情况下动态创建控件。

例如:我的xml文件将看起来像这样。

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <controls>
  3. <control>
  4. <type name="label">
  5. <property name="Visible" value="true"/>
  6. <property name="ID" value="Label1"/>
  7. .
  8. .
  9. .
  10. </type>
  11. </control>
  12. <control>
  13. <type name="TextBox">
  14. <property name="Visible" value="true"/>
  15. <property name="ID" value="TextBox1"/>
  16. .
  17. .
  18. .
  19. </type>
  20. </control>
  21. .
  22. .
  23. .
  24. </controls>

提前致谢。

解决方法

我会尽力为你提供一些提示,可能会给你一些想法。

一如既往,我们首先定义一个代表UI的视图模型:

  1. public class Myviewmodel
  2. {
  3. public Controlviewmodel[] Controls { get; set; }
  4. }
  5.  
  6. public abstract class Controlviewmodel
  7. {
  8. public abstract string Type { get; }
  9. public bool Visible { get; set; }
  10. public string Label { get; set; }
  11. public string Name { get; set; }
  12. }
  13.  
  14. public class TextBoxviewmodel : Controlviewmodel
  15. {
  16. public override string Type
  17. {
  18. get { return "textBox"; }
  19. }
  20. public string Value { get; set; }
  21. }
  22.  
  23. public class CheckBoxviewmodel : Controlviewmodel
  24. {
  25. public override string Type
  26. {
  27. get { return "checkBox"; }
  28. }
  29. public bool Value { get; set; }
  30. }
  31.  
  32. public class DropDownListviewmodel : TextBoxviewmodel
  33. {
  34. public override string Type
  35. {
  36. get { return "ddl"; }
  37. }
  38. public SelectList Values { get; set; }
  39. }

因此,我们定义了一些我们希望在应用程序中处理的基本控件。下一步将是有一个存储库方法,将查询数据库获取XML,然后一个映射层,最终将为我们提供一个我们的视图模型的实例。我把这个作为范围之外的这个答案,因为有很多方法可以实现它(XmlSerializer,XDocument,XmlReader,…)。

我想你已经有一个视图模型的实例。喜欢这个:

  1. public ActionResult Index()
  2. {
  3. var model = new Myviewmodel
  4. {
  5. Controls = new Controlviewmodel[]
  6. {
  7. new TextBoxviewmodel
  8. {
  9. Visible = true,Label = "label 1",Name = "TextBox1",Value = "value of textBox"
  10. },new CheckBoxviewmodel
  11. {
  12. Visible = true,Label = "check label",Name = "CheckBox1",Value = true
  13. },new DropDownListviewmodel
  14. {
  15. Visible = true,Label = "drop label",Name = "DropDown1",Values = new SelectList(
  16. new[]
  17. {
  18. new { Value = "1",Text = "text 1" },new { Value = "2",Text = "text 2" },new { Value = "3",Text = "text 3" },},"Value","Text","2"
  19. )
  20. }
  21. }
  22. };
  23. return View(model);
  24. }

所以我硬编码了一些值,以说明这个概念,但通常这个控制器动作看起来像这样一旦你实现了存储库和映射层:

  1. public ActionResult Index()
  2. {
  3. string xml = _repository.GetControls();
  4. var model = Mapper.Map<string,Myviewmodel>(xml);
  5. return View(model);
  6. }

OK,现在让我们移动到相应的Index.cshtml视图,它将包含以下形式:

  1. @model Myviewmodel
  2. @using (Html.BeginForm())
  3. {
  4. for (int i = 0; i < Model.Controls.Length; i++)
  5. {
  6. if (Model.Controls[i].Visible)
  7. {
  8. <div>
  9. @Html.HiddenFor(x => x.Controls[i].Type)
  10. @Html.HiddenFor(x => x.Controls[i].Name)
  11. @Html.EditorFor(x => x.Controls[i])
  12. </div>
  13. }
  14. }
  15. <input type="submit" value="OK" />
  16. }

OK,所以现在我们可以为我们想要处理的控件定义相应的编辑器模板:

>〜/ Views / Shared / EditorTemplates / TextBoxviewmodel.cshtml

  1. @model AppName.Models.TextBoxviewmodel
  2. @Html.LabelFor(x => x.Value,Model.Label)
  3. @Html.TextBoxFor(x => x.Value)

>〜/ Views / Shared / EditorTemplates / CheckBoxviewmodel.cshtml

  1. @model AppName.Models.CheckBoxviewmodel
  2. @Html.CheckBoxFor(x => x.Value)
  3. @Html.LabelFor(x => x.Value,Model.Label)

>〜/ Views / Shared / EditorTemplates / DropDownListviewmodel.cshtml

  1. @model AppName.Models.DropDownListviewmodel
  2. @Html.LabelFor(x => x.Value,Model.Label)
  3. @Html.DropDownListFor(x => x.Value,Model.Values)

到现在为止还挺好。在这个阶段,你应该能够渲染一个包含动态控件的窗体。但是当然这样的形式对任何人都是没用的。什么是好的是有可能POSTing此表单和捕获用户输入的值在控制器操作,以便我们可以处理它们。

控制器操作将如下所示:

  1. [HttpPost]
  2. public ActionResult Index(Myviewmodel model)
  3. {
  4. ... process the values
  5. }

现在这将是很好,但是当然不会工作,因为Controlviewmodel视图模型是一个抽象类,并且默认模型绑定器没有关于哪个具体实现实例化的线索。所以我们需要帮助他=>通过编写自定义模型绑定器:

  1. public class ControlModelBinder : DefaultModelBinder
  2. {
  3. protected override object CreateModel(ControllerContext controllerContext,ModelBindingContext bindingContext,Type modelType)
  4. {
  5. var type = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Type");
  6. object model = null;
  7. switch (type.AttemptedValue)
  8. {
  9. case "textBox":
  10. {
  11. model = new TextBoxviewmodel();
  12. break;
  13. }
  14. case "checkBox":
  15. {
  16. model = new CheckBoxviewmodel();
  17. break;
  18. }
  19. case "ddl":
  20. {
  21. model = new DropDownListviewmodel();
  22. break;
  23. }
  24. default:
  25. {
  26. throw new NotImplementedException();
  27. }
  28. };
  29.  
  30. bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model,model.GetType());
  31. return model;
  32. }
  33. }

它将在Application_Start中注册并关联到Controlviewmodel类型):

  1. ModelBinders.Binders.Add(typeof(Controlviewmodel),new ControlModelBinder());

猜你在找的asp.Net相关文章