2012-10-01 54 views
3

我有這個類如何自定義CSS EditorFor剃刀與

public class Contact 
{ 
    public int Id { get; set; } 
    public string ContaSurname { get; set; } 
    public string ContaFirstname { get; set; } 
    // and other properties... 
} 

我想創建異體我編輯所有這些領域的一種形式。所以我用這個代碼

<h2>Contact Record</h2> 

@Html.EditorFor(c => Model.Contact) 

這工作正常,但我想定製如何顯示元素。例如,我希望每個字段都顯示在與其標籤相同的行中。因爲現在,生成的HTML是這樣的:

<div class="editor-label"> 
    <label for="Contact_ContaId">ContaId</label> 
</div> 
<div class="editor-field"> 
    <input id="Contact_ContaId" class="text-box single-line" type="text" value="108" name="Contact.ContaId"> 
</div> 

回答

3

創建一個名爲Contact.cshtmlViews/Shared/EditorTemplates您的自定義標記的局部視圖。這將覆蓋默認編輯器。

正如@smartcavemen所述,請參閱Brad Wilson's blog瞭解模板的介紹。

+0

+1,我還想提一提:關於這個問題的Brad Wilson博客系列http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction .html – smartcaveman

+0

@smartcaveman感謝您的鏈接,我不記得是誰寫的那個系列。出於某種原因,我認爲這是scottgu! – jrummell

+0

感謝您的回答,它的工作! – kbaccouche

4

我同意jrummell以上的解決方案: 當您使用EditorFor -extension,你必須編寫自定義 編輯模板來描述可視化組件。

在某些情況下,我認爲使用具有相同數據類型的 幾個模型屬性的編輯器模板有點僵硬。在我的情況下,我想在我的模型中使用應顯示爲格式化字符串的十進制貨幣值。我想在我的視圖中使用相應的CSS類來設置這些屬性的樣式。

我已經看到其他的實現,其中的HTML參數已被附加到使用模型中的註釋屬性。這在我看來是不好的,因爲像CSS定義這樣的視圖信息應該在視圖中而不是在數據模型中設置。

所以我工作的另一種解決方案:

我的模型包含decimal?屬性,我想作爲一個貨幣領域使用。 問題是,我想在模型中使用數據類型decimal?,但在視圖中使用格式掩碼(例如「42,13€」)將格式化字符串中的十進制值顯示爲 。

這裏是我的模型定義:

[DataType(DataType.Currency), DisplayFormat(DataFormatString = "{0:C2}", ApplyFormatInEditMode = true)] 
public decimal? Price { get; set; } 

格式掩碼0:C2格式化decimal有2位小數。 ApplyFormatInEditMode很重要, 如果您要使用此屬性填充視圖中的可編輯文本字段。所以我把它設置爲true,因爲在我的情況下我想把它放到一個文本框中。

通常你必須在這樣的視圖使用EditorFor -extension:

<%: Html.EditorFor(x => x.Price) %> 

問題:

我不能在這裏添加CSS類,因爲我可以用Html.TextBoxFor例如做。

要提供自己的CSS類(或其他HTML屬性,如tabindex,或readonly)與EditorFor -extension是寫一個自定義的HTML-助手, 像Html.CurrencyEditorFor。下面是執行:

public static MvcHtmlString CurrencyEditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, Object htmlAttributes) 
{ 
    TagBuilder tb = new TagBuilder("input"); 

    // We invoke the original EditorFor-Helper 
    MvcHtmlString baseHtml = EditorExtensions.EditorFor<TModel, TValue>(html, expression); 

    // Parse the HTML base string, to refurbish the CSS classes 
    string basestring = baseHtml.ToHtmlString(); 

    HtmlDocument document = new HtmlDocument(); 
    document.LoadHtml(basestring); 
    HtmlAttributeCollection originalAttributes = document.DocumentNode.FirstChild.Attributes; 

    foreach(HtmlAttribute attr in originalAttributes) { 
    if(attr.Name != "class") { 
     tb.MergeAttribute(attr.Name, attr.Value); 
    } 
    } 

    // Add the HTML attributes and CSS class from the View 
    IDictionary<string, object> additionalAttributes = (IDictionary<string, object>) HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); 

    foreach(KeyValuePair<string, object> attribute in additionalAttributes) { 
    if(attribute.Key == "class") { 
     tb.AddCssClass(attribute.Value.ToString()); 
    } else { 
     tb.MergeAttribute(attribute.Key, attribute.Value.ToString()); 
    } 
    } 

    return MvcHtmlString.Create(HttpUtility.HtmlDecode(tb.ToString(TagRenderMode.SelfClosing))); 
} 

的想法是使用原始EditorFor -extension產生的HTML代碼,並解析這個HTML輸出字符串用我們自己的CSS類來代替創建 CSS的HTML屬性和追加其他額外的HTML屬性。對於HTML解析,我使用HtmlAgilityPack(使用谷歌)。

在視圖中,您可以使用這個助手是這樣的(不要忘記把相應的命名空間到你的視圖目錄web.config!):

<%: Html.CurrencyEditorFor(x => x.Price, new { @class = "mypricestyles", @readonly = "readonly", @tabindex = "-1" }) %> 

使用這個幫手,您的貨幣價值應在視圖中顯示得很好。

如果你想發佈你的視圖(表單),那麼通常所有的模型屬性將被髮送到你的控制器的操作方法。 在我們的例子中,將會提交一個字符串格式的十進制值,這個值將由ASP.NET MVC內部模型綁定類來處理。

由於此模型聯編程序期望decimal?值,但獲取字符串格式化的值,將引發異常。所以我們必須 將格式化的字符串轉換回decimal? - 表示。因此自己的ModelBinder - 實施是必要的,其中 將貨幣十進制值轉換回默認的十進制值(「42,13€」=>「42.13」)。

這裏就是這樣一個模型綁定的實現:

public class DecimalModelBinder : IModelBinder 
{ 

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     object o = null; 
     decimal value; 

     var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
     var modelState = new ModelState { Value = valueResult }; 

     try { 

     if(bindingContext.ModelMetadata.DataTypeName == DataType.Currency.ToString()) { 
      if(decimal.TryParse(valueResult.AttemptedValue, NumberStyles.Currency, null, out value)) { 
      o = value; 
      } 
     } else { 
      o = Convert.ToDecimal(valueResult.AttemptedValue, CultureInfo.CurrentCulture); 
     } 

     } catch(FormatException e) { 
     modelState.Errors.Add(e); 
     } 

     bindingContext.ModelState.Add(bindingContext.ModelName, modelState); 
     return o; 
    } 
} 

粘合劑已在global.asax文件應用程序的登記:

protected void Application_Start() 
{ 
    ... 

    ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder()); 
    ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder()); 

    ... 
} 

也許解決方案將幫助別人。