【问题标题】:MVC3, Razor, Html.TextAreaFor(): adjust height to fit contentsMVC3、Razor、Html.TextAreaFor():调整高度以适应内容
【发布时间】:2012-04-18 20:43:01
【问题描述】:

我目前在视图中使用以下代码来调整 Html.TextAreaFor() 的高度以适应其内容。有没有明显更好和/或更简洁的方法来做到这一点?

...
int width = 85;
int lines = 1;
string[] arr = Model.Text.Split(new string[] {"\r\n", "\n", "\r"}, StringSplitOptions.None);
foreach (var str in arr)
{
    if (str.Length / width > 0)
    {
        lines += str.Length / width + (str.Length % width <= width/2 ? 1 : 0);
    }
    else
    {
        lines++;
    }
}
@Html.TextAreaFor(m => m.Text,
                  new
                  {
                      id = "text",
                      style = "width:" + width + "em; height:" + lines + "em;"
                  })

...

【问题讨论】:

    标签: asp.net-mvc razor html-helper


    【解决方案1】:

    代码看起来不错。一种可能的改进是将其外部化为可重用的助手以避免污染视图:

    public static class TextAreaExtensions
    {
        public static IHtmlString TextAreaAutoSizeFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            object htmlAttributes
        )
        {
            var model = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model;
            var text = model as string ?? string.Empty;
            int width = 85;
            int lines = 1;
            string[] arr = text.Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);
            foreach (var str in arr)
            {
                if (str.Length / width > 0)
                {
                    lines += str.Length / width + (str.Length % width <= width / 2 ? 1 : 0);
                }
                else
                {
                    lines++;
                }
            }
            var attributes = new RouteValueDictionary(htmlAttributes);
            attributes["style"] = string.Format("width:{0}em; height:{1}em;", width, lines);
            return htmlHelper.TextAreaFor(expression, attributes);
        }
    }
    

    在视图中:

    @Html.TextAreaAutoSizeFor(m => m.Text, new { id = "text" })
    

    【讨论】:

    • 可重复使用,使维护更容易,并使视图整洁......并且像魅力一样工作!只需添加 using 指令: using System.Web.Routing;使用 System.Web.Mvc;使用 System.Web.Mvc.Html;使用 System.Linq.Expressions;
    【解决方案2】:

    看起来不错, 您也可以使用JQuery autogrow textarea plugin

    它将为您节省一些编码,甚至可能更高效。

    【讨论】:

    • 很棒的插件。在这个答案和达林·季米特洛夫的答案之间徘徊!可能比我需要的要花哨一点。
    【解决方案3】:

    您可以使用一些 LINQ 魔法将其简化为一行:

    var lines = Model.Text.Split( new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None )
      .Aggregate( 0, (total, next) => 
        total += next.Length <= width ? 1 
          : (int)Math.Ceiling( (double)next.Length / width ) );
    

    请注意,您的拆分方式存在小问题。如果您的输入中确实有混合的\n\r\r\n 行尾(不太可能),则此拆分将按从左到右的顺序拆分,因此它永远不会在字符串\r\n 上拆分,这意味着\r\n 之间有一个空行。所以你会看到我将\r\n 移动为拆分中的第一个字符串。

    【讨论】:

    • 你是对的;我在答案中纠正了这个问题。好收获!
    • 感谢您的修复。紧凑且有效!将它与达林的答案结合使用。