Шаблон ASP.Net MVC Editor для динамического просмотра данных / форм - PullRequest
3 голосов
/ 13 сентября 2011

Я реализую веб-приложение MVC3 / Razor, которое извлекает некоторые из своих «полей», которые пользователь может редактировать из других служб, поэтому список свойств для редактирования в представлении является полностью динамическим и неизвестным во время компиляции.

Я написал несколько помощников по частичному просмотру и HTML, которые перебирают группы и свойства, полученные из других сервисов. Сейчас я нахожусь в точке, где мне нужно построить теги для различных типов свойств, и подумал, почему бы не использовать систему шаблонов редактора MVC для этого? Существует поддержка различных типов данных (например, флажки и т. Д.), И даже можно настроить их с помощью моих пользовательских шаблонов.

Пока все хорошо, но как я могу использовать Html.EditorFor() или Html.Editor() для пользовательских объектов данных / свойств? Значение для построения динамических форм без статических типизированных данных в качестве модели представления.

Вот минималистичный пример моего кода помощника HTML:

public static MvcHtmlString GetField(this HtmlHelper helper, Field field)
{
...
   return helper.EditorFor(field, m => m.Value);
...
}

Свойство "поле" - это поле, которое я получил от внешних служб. У него есть свойство «Значение» типа object. Мне нравится создавать код редактора для этого типа свойства.

Как я понимаю, шаблоны редактора построены на текущей модели представления. Могу ли я передать другой объект в качестве модели, а не текущей модели представления (например, в приведенном выше примере «поле»)?

Любая помощь будет отличной!

Ура, Марк

1 Ответ

3 голосов
/ 13 сентября 2011

Моя первая задача ASP MVC заключалась в создании динамической формы, и она не проста.
По сути, вы не можете использовать встроенные помощники или проверки, потому что они ожидают строго типизированных объектов.

Мое представление в основном перебирает поля ввода, проверяет тип данных (bool, int, string, datetime и т. Д.) И создает редактор непосредственно для этого типа.

Вы также должны выполнить всю свою проверку вручную, с украшением типов атрибутами, чтобы это не сработало, см. Мой вопрос , если (ModelState.IsValid) не работает с FormsCollection. Что использовать вместо?

Razor View logic (мы используем расширения DevExpress MVC, но вы получаете дрейф)
Объект формы и его коллекция Fields являются нашими объектами на заказ, которые описывают, как должна выглядеть форма (на странице собраны критерии поиска, поэтому в коде вы увидите критерии и имена типов поиска).

<table id="criteriaTable">
@foreach (var field in form.Fields)
{
    <tr id="criteriaTableRow">
    @if (field.IsVisible)
    { 
    <td id="criteriaTableLabelCol"> 
       @Html.DevExpress().Label(s => s.Text = field.Caption).GetHtml()
    </td>
    <td id="criteriaTableEditCol">
        @if (field.Type == typeof(bool))
        {
           @Html.CheckBox(s =>
      {
          s.Checked = field.IsBoolSet;
          s.Name = field.Name;
          s.ClientEnabled = !field.IsReadonly;
      }).GetHtml()
        }
        else if (field.Type == typeof(DateTime))
        {
            Html.DevExpress().DateEdit(s =>
            {
                s.Name = field.Name;
                s.ClientEnabled = !field.IsReadonly;
                if (!string.IsNullOrEmpty(field.Value))
                {
                    DateTime dateValue;
                    if (DateTime.TryParse(field.Value, out dateValue))
                        s.Date = dateValue;
                }
            }).GetHtml();
        }
        else if (field.ListValues.Count > 0)
        {
            <input type="hidden" id="@("initiallySelected" + field.Name)" value="@field.Value" />
            Html.DevExpress().ListBox(s =>
            {
                s.Name = field.Name;
                s.ClientVisible = field.IsVisible;
                s.ClientEnabled = !field.IsReadonly;
                s.Properties.SelectionMode = DevExpress.Web.ASPxEditors.ListEditSelectionMode.CheckColumn;
                s.Properties.TextField = "Name";
                s.Properties.ValueField = "Value";
                s.Properties.ValueType = typeof(string);

                //s.Properties.EnableClientSideAPI = true;
                foreach (var item in field.ListValues)
                {
                    s.Properties.Items.Add(item.Name, item.Value);
                }

                //s.Properties.ClientSideEvents.SelectedIndexChanged = "MultiSelectListChanged";
                s.Properties.ClientSideEvents.Init = "MultiSelectListInit";
            }).GetHtml();

        }
        else
        {
            //Html.TextBox(field.Name, field.Value)
            Html.DevExpress().TextBox(s =>
            {
                s.Name = field.Name; s.Text = field.Value;
            }).GetHtml();
        }
        @Html.ValidationMessage(field.Name)
        <input type="hidden" name="@("oldvalue_" + field.Name)" value="@field.Value" />
        <input type="hidden" name="@("olduse_" + field.Name)" value="@(field.IncludeInSearch ? "C" : "U")" />
    </td>
    <td id="criteriaTableIncludeCol"> 
        @Html.DevExpress().CheckBox(s =>
   {
       s.Checked = field.IncludeInSearch;
       s.Name = "use_" + field.Name;
       s.ClientEnabled = (!field.IsMandatory);
   }).GetHtml()
    </td>
    }
    </tr>
}
    </table>

Действие Controller принимает коллекцию форм. Я перебираю formCollection в поисках имен элементов управления, указанных в представлении.

[HttpPost]
public ActionResult QueryCriteria(FormCollection formCollection)
{
    var isValid = true;
    foreach (var field in form.Fields)
    {
        var value = (formCollection[field.Name] ?? "").Trim();
        ...

Если есть какие-либо ошибки проверки, я могу указать проверку уровня управления, добавив ModelError непосредственно в модель, например.

ModelState.AddModelError(field.Name, "This is a mandatory field");

и я возвращаю вид, если есть ошибки проверки.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...