asp.net-mvc 如何基于XML文件在MVC 3中动态创建控件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6329461/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create controls dynamically in MVC 3 based on an XML file
提问by BonDaviD
I have a XML file stored in the database as XML format which contains some controls like drop down text box, label text area, etc. which may or may not have initial values. So my aim is to read the XML file and based on the control type, I need to create that control dynamically and associate the initial value if any and the preview of the page have to be shown in a view. Anybody please help me how to create the controls dynamically in MVC 3 for this scenario.
我有一个 XML 文件作为 XML 格式存储在数据库中,其中包含一些控件,如下拉文本框、标签文本区域等,这些控件可能有也可能没有初始值。所以我的目标是读取 XML 文件,并根据控件类型,我需要动态创建该控件并关联初始值(如果有的话),并且必须在视图中显示页面的预览。任何人都请帮助我如何在 MVC 3 中为这种情况动态创建控件。
For eg: my xml file will look something like this.
例如:我的 xml 文件看起来像这样。
<?xml version="1.0" encoding="utf-8" ?>
<controls>
<control>
<type name="label">
<property name="Visible" value="true"/>
<property name="ID" value="Label1"/>
.
.
.
</type>
</control>
<control>
<type name="TextBox">
<property name="Visible" value="true"/>
<property name="ID" value="TextBox1"/>
.
.
.
</type>
</control>
.
.
.
</controls>
Thanks in advance.
提前致谢。
回答by Darin Dimitrov
I will try to provide you with some hints that might give you some ideas.
我将尝试为您提供一些可能会给您一些想法的提示。
As always let's start by defining a view model which will represent the UI:
和往常一样,让我们首先定义一个表示 UI 的视图模型:
public class MyViewModel
{
public ControlViewModel[] Controls { get; set; }
}
public abstract class ControlViewModel
{
public abstract string Type { get; }
public bool Visible { get; set; }
public string Label { get; set; }
public string Name { get; set; }
}
public class TextBoxViewModel : ControlViewModel
{
public override string Type
{
get { return "textbox"; }
}
public string Value { get; set; }
}
public class CheckBoxViewModel : ControlViewModel
{
public override string Type
{
get { return "checkbox"; }
}
public bool Value { get; set; }
}
public class DropDownListViewModel : TextBoxViewModel
{
public override string Type
{
get { return "ddl"; }
}
public SelectList Values { get; set; }
}
So we have defined some of the basic controls we would like to handle in our application. The next step would be to have a repository method which will query the database, fetch the XML and then a mapping layer that will finally provide us with an instance of our view model. I am leaving this as out of scope for this answer as there are many ways you could implement it (XmlSerializer, XDocument, XmlReader, ...).
所以我们已经定义了一些我们想要在我们的应用程序中处理的基本控件。下一步是拥有一个存储库方法,它将查询数据库,获取 XML,然后是一个映射层,最终为我们提供视图模型的实例。我将其视为超出此答案的范围,因为您可以通过多种方式实现它(XmlSerializer、XDocument、XmlReader 等)。
I suppose that you already have an instance of the view model. Like this:
我想你已经有了一个视图模型的实例。像这样:
public ActionResult Index()
{
var model = new MyViewModel
{
Controls = new ControlViewModel[]
{
new TextBoxViewModel
{
Visible = true,
Label = "label 1",
Name = "TextBox1",
Value = "value of textbox"
},
new CheckBoxViewModel
{
Visible = true,
Label = "check label",
Name = "CheckBox1",
Value = true
},
new DropDownListViewModel
{
Visible = true,
Label = "drop label",
Name = "DropDown1",
Values = new SelectList(
new[]
{
new { Value = "1", Text = "text 1" },
new { Value = "2", Text = "text 2" },
new { Value = "3", Text = "text 3" },
}, "Value", "Text", "2"
)
}
}
};
return View(model);
}
So I have hardcoded some values in order to illustrate the concept, but normally this controller action would look something like this once you implement the repository and mapping layer:
所以我硬编码了一些值来说明这个概念,但通常一旦你实现了存储库和映射层,这个控制器操作看起来像这样:
public ActionResult Index()
{
string xml = _repository.GetControls();
var model = Mapper.Map<string, MyViewModel>(xml);
return View(model);
}
OK, now let's move to the corresponding Index.cshtml
view which will contain the form:
好的,现在让我们转到Index.cshtml
包含表单的相应视图:
@model MyViewModel
@using (Html.BeginForm())
{
for (int i = 0; i < Model.Controls.Length; i++)
{
if (Model.Controls[i].Visible)
{
<div>
@Html.HiddenFor(x => x.Controls[i].Type)
@Html.HiddenFor(x => x.Controls[i].Name)
@Html.EditorFor(x => x.Controls[i])
</div>
}
}
<input type="submit" value="OK" />
}
OK, so now we can define the corresponding editor templates for the controls we would like to handle:
好的,现在我们可以为我们要处理的控件定义相应的编辑器模板:
~/Views/Shared/EditorTemplates/TextBoxViewModel.cshtml
@model AppName.Models.TextBoxViewModel @Html.LabelFor(x => x.Value, Model.Label) @Html.TextBoxFor(x => x.Value)
~/Views/Shared/EditorTemplates/CheckBoxViewModel.cshtml
@model AppName.Models.CheckBoxViewModel @Html.CheckBoxFor(x => x.Value) @Html.LabelFor(x => x.Value, Model.Label)
~/Views/Shared/EditorTemplates/DropDownListViewModel.cshtml
@model AppName.Models.DropDownListViewModel @Html.LabelFor(x => x.Value, Model.Label) @Html.DropDownListFor(x => x.Value, Model.Values)
~/Views/Shared/EditorTemplates/TextBoxViewModel.cshtml
@model AppName.Models.TextBoxViewModel @Html.LabelFor(x => x.Value, Model.Label) @Html.TextBoxFor(x => x.Value)
~/Views/Shared/EditorTemplates/CheckBoxViewModel.cshtml
@model AppName.Models.CheckBoxViewModel @Html.CheckBoxFor(x => x.Value) @Html.LabelFor(x => x.Value, Model.Label)
~/Views/Shared/EditorTemplates/DropDownListViewModel.cshtml
@model AppName.Models.DropDownListViewModel @Html.LabelFor(x => x.Value, Model.Label) @Html.DropDownListFor(x => x.Value, Model.Values)
So far, so good. At this stage you should be able to render a form containing the dynamic controls. But of course such a form is pretty useless to anyone. What would be nice is to have the possibility of POSTing this form and capturing the values entered by the user in a controller action so that we could process them.
到现在为止还挺好。在此阶段,您应该能够呈现包含动态控件的表单。但当然,这种形式对任何人来说都毫无用处。最好是有可能发布这个表单并捕获用户在控制器操作中输入的值,以便我们可以处理它们。
The controller action would look like this:
控制器动作如下所示:
[HttpPost]
public ActionResult Index(MyViewModel model)
{
... process the values
}
Now that would be nice but of course it won't work because the ControlViewModel
view model is an abstract class and the default model binder has no clue about which specific implementation to instantiate. So we need to help him => by writing a custom model binder:
现在这会很好,但当然它不会工作,因为ControlViewModel
视图模型是一个抽象类,并且默认模型绑定器不知道要实例化哪个特定实现。所以我们需要通过编写自定义模型绑定器来帮助他 =>:
public class ControlModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var type = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Type");
object model = null;
switch (type.AttemptedValue)
{
case "textbox":
{
model = new TextBoxViewModel();
break;
}
case "checkbox":
{
model = new CheckBoxViewModel();
break;
}
case "ddl":
{
model = new DropDownListViewModel();
break;
}
default:
{
throw new NotImplementedException();
}
};
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType());
return model;
}
}
which will be registered in Application_Start
and associated to the ControlViewModel
type):
将在Application_Start
该ControlViewModel
类型中注册并关联):
ModelBinders.Binders.Add(typeof(ControlViewModel), new ControlModelBinder());
回答by Dawid Rutkowski
It seems to be quite simple in fact. Get your XML from the database, parse it and put it into some model classes. Those classed will contains controls data.
其实看起来很简单。从数据库中获取您的 XML,对其进行解析并将其放入一些模型类中。那些分类的将包含控件数据。
Next create partial view which will dynamicly build required controls depending on model.
接下来创建部分视图,它将根据模型动态构建所需的控件。
At the end, call that action from jQuery ajax and put returned HTML in the proper place.
最后,从 jQuery ajax 调用该操作并将返回的 HTML 放在适当的位置。
Quick, easy, no reaload....
快速,简单,无需重新加载....
回答by Muhammad Adeel Zahid
you can pass a model to your strongly typed view andwrite a html helper named Html.ControlFor in the helper you can read the xml file and create controls (input, select etc.) based on match of property name (where property name matches property tag in xml file)
您可以将模型传递给强类型视图并在帮助器中编写一个名为 Html.ControlFor 的 html 帮助器,您可以读取 xml 文件并根据属性名称的匹配(其中属性名称与属性标签匹配)创建控件(输入、选择等)在 xml 文件中)