如何基于XML文件中的MVC 3动态创建控件 [英] How to create controls dynamically in MVC 3 based on an XML file

查看:108
本文介绍了如何基于XML文件中的MVC 3动态创建控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有存储在数据库中作为XML格式,其中包含像下拉文本框,标记文本区域等,其可以或可以不具有初始值某些控件一个XML文件。所以我的目的是读取XML文件,并根据控制类型,我需要动态创建的控制和初始值(如果有)和页面的preVIEW在一个视图中显示相关联。有人请帮助我如何创建控件动态地MVC 3此方案。

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文件看起来像这样

For eg: my xml file will look something like this.

<?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>

先谢谢了。

推荐答案

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

I will try to provide you with some hints that might give you some ideas.

与往常一样,让我们​​通过定义将重新present的UI视图模型启动:

As always let's start by defining a view model which will represent the 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; }
}

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

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, ...).

我想你已经拥有的视图模型的实例。像这样的:

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);
}

所以我很难codeD为了说明这个概念的一些值,但通常这个控制器操作看起来像这样的东西,一旦你实现了资源库和映射层:

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);
}

好了,现在让我们继续前进到其中将包含形成相应的 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:


  • 〜/查看/共享/ EditorTemplates / TextBoxViewModel.cshtml

@model AppName.Models.TextBoxViewModel
@Html.LabelFor(x => x.Value, Model.Label)
@Html.TextBoxFor(x => x.Value)


  • 〜/查看/共享/ EditorTemplates / CheckBoxViewModel.cshtml

    @model AppName.Models.CheckBoxViewModel
    @Html.CheckBoxFor(x => x.Value)
    @Html.LabelFor(x => x.Value, Model.Label)
    


  • 〜/查看/共享/ EditorTemplates / DropDownListViewModel.cshtml

    @model AppName.Models.DropDownListViewModel
    @Html.LabelFor(x => x.Value, Model.Label)
    @Html.DropDownListFor(x => x.Value, Model.Values)
    


  • 到目前为止,一切都很好。在这个阶段,你应该能够使包含动态控件的窗体。不过,当然这样的形式为pretty没用任何人。什么是不错是有张贴本形式和捕捉用户在一个控制器动作进入这样我们就可以处理它们的值的可能性。

    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
    }
    

    现在这将是很好,但当然也不会工作,因为 ControlViewModel 视图模型是一个抽象类,默认模式粘结剂不知道哪个具体的实施实例。因此,我们需要通过编写自定义模型绑定,以帮助他=>:

    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:

    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;
        }
    }
    

    这将在的Application_Start 注册并关联到的

    ControlViewModel 键入):

    which will be registered in Application_Start and associated to the ControlViewModel type):

    ModelBinders.Binders.Add(typeof(ControlViewModel), new ControlModelBinder());
    

    这篇关于如何基于XML文件中的MVC 3动态创建控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆