MVC3 Razor Html.TextBoxFor: Can I make it Multi-Line like TextAreaFor?

会有一股神秘感。 提交于 2019-12-11 17:41:23

问题


I've already seen this post: Changing the size of Html.TextBox

But I cannot change to Html.TextAreaFor() because it does not have an attribute for me to set a dynamic default value (I am making an edit page that I want to dynamically fill in the fields of the current data which can then be modified). I also can't seem to get the EditorFor to work even if I change to [DataType(DataType.MultilineText)] in my viewmodel (all it does it seem to change to textboxfor and my default values do not show up).

My edit view takes in a viewmodel containing two models, an empty form (OfferForm) to be filled with the onscreen fields, and the offer model containing the current data. I want to have textfields for the OfferForm, and dynamically fill them with the contents of the offer model's data.

Here is my html:

<div class="InLine">
                    <div class="InLine editor-label-container">
                        <div class="editor-label">
                            @Html.LabelFor(model => model.OfferForm.Description)
                        </div>
                    </div>
                    <div class="InLine editor-field-container">
                        <div class="editor-field">
                            @Html.TextBoxFor(model => model.OfferForm.Description, new { @Value = @Html.DisplayFor(model => model.Offer.Description)})
                            @Html.ValidationMessageFor(model => model.Offer.Description)
                        </div>
                    </div>
                </div>
                <div class="InLine">
                    <div class="InLine editor-label-container">
                        <div class="editor-label">
                            @Html.LabelFor(model => model.OfferForm.SMSText)
                        </div>
                    </div>
                    <div class="InLine editor-field-container">
                        <div class="editor-field">
                            @Html.TextBoxFor(model => model.OfferForm.SMSText, new { @Value = @Html.DisplayFor(model => model.Offer.SmsText)})
                            @Html.ValidationMessageFor(model => model.Offer.SmsText)
                        </div>
                    </div>
                </div>

Is there a way to set a "multiline" attribute in the Html.TextBoxFor()?


回答1:


The simplest way to proceed would be to create an Html extension method like the following

public static class HtmlTextAreaExtensions {

    public static IHtmlString TextAreaFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, int rows, int cols, object htmlAttributes = null, string Value = null) {
        return TextAreaFor<TModel, TProperty>(htmlHelper, expression, rows, cols, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), Value);
    }

    public static IHtmlString TextAreaFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, int rows, int cols, IDictionary<string, string> htmlAttributes = null, string Value = null) {
        var modelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        var name = ExpressionHelper.GetExpressionText(expression);

        string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

        Dictionary<string, object> rowsAndColumns = new Dictionary<string, object>();
        if (rows > 0) {
            rowsAndColumns.Add("rows", rows.ToString(CultureInfo.InvariantCulture));
        } else {
            rowsAndColumns.Add("rows", "5");
        }
        if (cols > 0) {
            rowsAndColumns.Add("cols", cols.ToString(CultureInfo.InvariantCulture));
        } else {
            rowsAndColumns.Add("cols", "20");
        }
        TagBuilder tagBuilder = new TagBuilder("textarea");
        tagBuilder.GenerateId(fullName);
        tagBuilder.MergeAttributes(htmlAttributes, true);
    tagBuilder.MergeAttributes(rowsAndColumns, false);  // Only force explicit rows/cols
        tagBuilder.MergeAttribute("name", fullName, true);

        // If there are any errors for a named field, we add the CSS attribute.
        ModelState modelState;
        if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState) && modelState.Errors.Count > 0) {
            tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
        }

        tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name));

        string value;
        if (Value != null) {
            value = Value;
        } else if (modelState != null && modelState.Value != null) {
            value = modelState.Value.AttemptedValue;
        } else if (modelMetadata.Model != null) {
            value = modelMetadata.Model.ToString();
        } else {
            value = String.Empty;
        }

        // The first newline is always trimmed when a TextArea is rendered, so we add an extra one
        // in case the value being rendered is something like "\r\nHello".
        tagBuilder.SetInnerText(Environment.NewLine + value);

        return new HtmlString(tagBuilder.ToString(TagRenderMode.Normal));
    }
}

You could then call it:

@Html.TextAreaFor(f => f.ModelProperty, Value=f.SomeOtherModelProperty)

It only supports basic features and what not. The actual tag generation was pulled from Mvc3 source with slight changes to support passing the value in. This should work for most cases but you might need to add more overrides. This isn't very...clean but should get you going. :)

To get the extension to show up inside your razor views you edit the Web.config within the Views directory and add the namespace (not the class name) where you put this class. It should then show up in intellisense.




回答2:


You have to realize that HTML elements are not windows controls, they just map to them somewhat.

HTML elements have to be cross platform, and there is no guarantee that a textarea is just a multi-line textbox on all platforms, so as far as HTML is concerned a textbox and a textarea are two different things.

So the answer is no, because there is no multiline attribute for a textbox in HTML.



来源:https://stackoverflow.com/questions/6740890/mvc3-razor-html-textboxfor-can-i-make-it-multi-line-like-textareafor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!