Подтвердить что ты не робот

Как создавать элементы управления динамически в MVC 3 на основе XML файла

У меня есть XML файл, хранящийся в базе данных, в формате XML, который содержит некоторые элементы управления, такие как раскрывающееся текстовое поле, область текста ярлыка и т.д., которые могут иметь или не иметь начальные значения. Поэтому моя цель - прочитать XML файл и на основе типа управления, мне нужно создать этот элемент управления динамически и связать начальное значение, если в представлении нужно показать и просмотреть его. Кто-нибудь, пожалуйста, помогите мне, как создавать элементы управления динамически в MVC 3 для этого сценария.

Например, мой 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>

Спасибо заранее.

4b9b3361

Ответ 1

Я попытаюсь предоставить вам некоторые подсказки, которые могут дать вам некоторые идеи.

Как всегда, давайте начнем с определения модели представления, которая будет представлять пользовательский интерфейс:

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

Я предполагаю, что у вас уже есть экземпляр модели представления. Вот так:

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

Итак, для иллюстрации концепции я жестко закодировал некоторые значения, но обычно это действие контроллера будет выглядеть примерно так, как только вы реализуете слой репозитория и отображения:

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" />
}

ОК, поэтому теперь мы можем определить соответствующие шаблоны редактора для элементов управления, которые мы хотели бы обрабатывать:

  • ~/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)
    

До сих пор так хорошо. На этом этапе вы должны иметь возможность отображать форму, содержащую динамические элементы управления. Но, конечно, такая форма для всех бесполезна. Было бы неплохо иметь возможность POSTing этой формы и захват значений, введенных пользователем в действии контроллера, чтобы мы могли их обработать.

Действие контроллера будет выглядеть следующим образом:

[HttpPost]
public ActionResult Index(MyViewModel model)
{
    ... process the values
}

Теперь это было бы неплохо, но, конечно, это не сработает, потому что модель просмотра 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;
    }
}

который будет зарегистрирован в Application_Start и связан с типом ControlViewModel):

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

Ответ 2

На самом деле это довольно просто. Получите XML из базы данных, проанализируйте его и поместите в некоторые классы моделей. Те, кто классифицирован, будут содержать данные управления.

Далее создайте частичное представление, которое будет динамически создавать необходимые элементы управления в зависимости от модели.

В конце вызовите это действие из jQuery ajax и верните HTML-код в нужное место.

Быстро, легко, без реальной нагрузки....

Ответ 3

вы можете передать модель своему строго типизированному представлению andwrite html helper с именем Html.ControlFor в помощнике вы можете прочитать xml файл и создать элементы управления (ввод, выбор и т.д.) на основе соответствия имени свойства (где имя свойства соответствует тегу свойства в файле xml)