ASP MVC 5.2 с использованием вложенных словарей для htmlAttributes в EditorFor

Я хочу передать вложенный словарь в EditorFor viewData.

@{
    var viewData = new RouteValueDictionary();
    var htmlAttributes = new RouteValueDictionary();
    htmlAttributes.Add("title", "foo");
    viewData["htmlAttributes"] = htmlAttributes;
}
Html.EditorFor(model => model.SomeProperty, viewData);

Проблема в том, что tile="foo" не отображается. Когда я использую

var htmlAttributes = new {title = "foo"};

все работает как положено.

Мне нужно, чтобы htmlAttributes был словарем, потому что в моем приложении он генерируется динамически.

Итак, как я могу передать словарь туда. Я уже пытался передать thmlAttributes как ExpandoObject, но это тоже не работает.


person wertzui    schedule 09.12.2014    source источник


Ответы (2)


Боюсь, это невозможно сделать, по крайней мере, не так просто, потому что EditorFor создает много html-элементов, и поэтому неясно, к какому элементу следует применять htmlAttributes.

Однако сложный способ — реализовать собственный Object.cshtml в Views/Shared/EditorTemplates/Object.cshtml. Ниже приведен пример пользовательского Object.cshtml (для начальной загрузки), где вы можете получить значения из ViewData и построить выходной Html любым удобным для вас способом.

@using MvcApplication1.Utility
@if (ViewData.TemplateInfo.TemplateDepth > 1) {
    @ViewData.ModelMetadata.SimpleDisplayText
} else {
    foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm))) {
        var htmlString = prop.IsReadOnly ? Html.Display(prop.PropertyName) : Html.Editor(prop.PropertyName);
        if (prop.HideSurroundingHtml) {
            @htmlString
        }
        else
        {
            var errors = Html.ValidationErrors(prop);
            <div class="form-group @(prop.IsReadOnly ? "form-group-readonly" : "") @(errors.Any() ? "has-error has-feedback" : "")">
                <label class="control-label" for="@ViewData.TemplateInfo.GetFullHtmlFieldId(prop.PropertyName)">@prop.GetDisplayName()</label>
                @htmlString
                @foreach (var err in errors)
                {
                    <div class="field-validation-error">@err.ErrorMessage</div>
                }
            </div>
        }
    }
}

и функции полезности

    public static IEnumerable<ModelError> ValidationErrors<TModel>(this HtmlHelper<TModel> htmlHelper, ModelMetadata modelMetadata)
    {
        string modelName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(modelMetadata.PropertyName);
        return ValidationErrors(htmlHelper, modelName);
    }

    public static IEnumerable<ModelError> ValidationErrors<TModel>(this HtmlHelper<TModel> htmlHelper)
    {
        return ValidationErrors(htmlHelper, String.Empty);
    }

    private static IEnumerable<ModelError> ValidationErrors(this HtmlHelper htmlHelper, String modelName)
    {
        FormContext formContext = htmlHelper.ViewContext.FormContext;
        if (formContext == null)
            yield break;

        if (!htmlHelper.ViewData.ModelState.ContainsKey(modelName))
            yield break;

        ModelState modelState = htmlHelper.ViewData.ModelState[modelName];
        if (modelState == null)
            yield break;

        ModelErrorCollection modelErrors = modelState.Errors;
        if (modelErrors == null)
            yield break;

        foreach(var err in modelErrors)
            yield return err;
    }
person Ibrahim ben Salah    schedule 09.12.2014
comment
В данном случае я использую его для простого строкового свойства, которое должно отображаться как текстовое поле. А начиная с MVC 5.1 можно добавить свойство htmlAttributes в дополнительный параметр ViewData, который отображается как атрибуты html. Так что это не должно быть проблемой. - person wertzui; 09.12.2014
comment
В этом случае вместо этого используйте Html.TextBoxFor - person Ibrahim ben Salah; 09.12.2014
comment
Но я хотел бы использовать его в EditorFor, потому что таким образом я также могу использовать свой собственный шаблон, который может содержать 2 текстовых поля. При использовании EditorFor эти htmlAttributes будут записаны в ViewData и автоматически будут выбраны всеми текстовыми полями в этом пользовательском шаблоне. - person wertzui; 10.12.2014
comment
Это просто не работает так, как вы используете EditorFor, пожалуйста, внимательно прочитайте мой ответ - person Ibrahim ben Salah; 11.12.2014

В настоящее время это невозможно (MVC 5.2), см. эту ошибку: https://aspnetwebstack.codeplex.com/workitem/1736

person wertzui    schedule 15.12.2014