2011-07-19 22 views
0

我已经看到了这个帖子:Changing the size of Html.TextBoxMVC3剃刀Html.TextBoxFor:我可以使它像TextAreaFor多线?

但因为它没有一个属性为我设定一个动态的默认值(我在做,我要动态地填写在编辑页面,我不能改变Html.TextAreaFor()然后可以修改当前数据的字段)。即使我在我的viewmodel中更改为[DataType(DataType.MultilineText)](但它似乎更改为textboxfor,并且我的默认值不显示),我似乎也无法让EditorFor工作。

我的编辑视图需要一个包含两个模型的视图模型,一个空的窗体(OfferForm)用屏幕字段填充,offer模型包含当前数据。我想为OfferForm设置文本字段,并动态填充offer模型数据的内容。

这里是我的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> 

有没有办法设置在Html.TextBoxFor()一个 “multiline” 属性?

+0

你为什么想要设置'value'属性。在文本区域中,'value'是html元素中包含的内容。至于你的例子,你不需要为'TextBoxFor'或'TextAreaFor'设置value属性,就像你使用'Html。*'助手一样,它会自动填充值。 – Buildstarted

+0

@BuildStarted - 我需要设置'Value'的原因是因为该值不是从我使用'TextBoxFor'或'TextAreaFor'的模型(即空白OfferForm)填充的。相反,它是从ViewModel中的第二个模型(即Offer)填充的。 –

+0

啊,我明白了。非常微妙的命名差异。 – Buildstarted

回答

2

继续将创建一个HTML扩展方法,像下面

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

然后你可以把它简单的方法:

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

它仅支持基本的功能,什么不是。实际的标签生成是从Mvc3源代码中稍作修改以支持将值传入。这应该适用于大多数情况,但您可能需要添加更多覆盖。这不是很干净,但应该让你走。 :)

为了得到扩展,以显示你的剃须刀的意见里面你编辑浏览目录内Web.config并添加命名空间(不是类名),你把这个类。它应该在智能感知中出现。

+0

这看起来完全像我所需要的,但是我之前从未做过Html.Helper扩展。我看了这个页面[如何创建Html助手](http://develoq.net/2011/how-to-create-custom-html-helpers-for-asp-net-mvc-3-and-razor-view -engine /),但扩展名只是进入Models文件夹?我将我的类的名称空间添加到web.config。如果你确定它应该被调用,我会不断收到错误信息:'名称'值'在当前上下文中不存在'。 –

+0

这不是一个html助手,而是一个扩展。我已经用完整的课程更新了答案,并简要地提出了如何让它在视图中运行的问题。 – Buildstarted

+0

你是男人!非常感谢。它的工作就像我想要的:)。下面是我在views目录里添加命名空间到web.config后的调用方式:'@ Html.TextAreaFor(model => model.OfferForm.Description,5,1,null,Html.DisplayFor(model => model.Offer.Description).ToString())' –

3

你必须认识到,HTML元素 Windows控件,他们只是映射到他们一些。

HTML元素必须是跨平台的,并且不能保证textarea只是所有平台上的多行文本框,因此就HTML而言,textbox和textarea是两个不同的东西。

所以答案是否定的,因为HTML中的文本框没有多行属性。

+0

因此,没有办法使用默认值参数的多行文本框或textarea?如果我将它用作EditorFor(Offer),我可以让编辑做我想做的事情,但是我想要EditorFor(OfferForm),但我希望它包含优惠信息,所以我不能这样做。我运气不好吗? –

+1

@Evan Layman - 我不知道默认值,我只是回答你关于多行文本框的问题。 –

+0

谢谢感谢您的回答,我只是希望有一些方法可以让html元素以我想要的形式出现:) –