2013-08-10 14 views
14

Jestem niezadowolony z obecnej implementacji DropDownList, ponieważ tak naprawdę nie mogę wiele zrobić z tagami opcji (tylko wybrane, tekst i wartość są obsługiwane). Chcę zrobić własne, gdzie mogę ustawić wyłączone i inne rzeczy na poszczególnych opcjach.Tworzenie własnego rozszerzenia HtmlHelper dla danych wejściowych zgodnego z powiązaniem modelu

Obecnie zmieniam opcje przez javascript, ale myślę, że jest to trochę odstręczający sposób, i wolę po prostu renderować poprawny html na początek.

Wiem, że mogę po prostu zrobić szablon, który używa znaczników opcji i opcji i tworzyć opcje tak, jak chcę je - ale normalne rozszerzenie DropDownList dodaje stuff rzeczy i konkretną nazwę i identyfikator, który przypuszczam jest dla właściwego wiązania danych, gdy przesłanie formularza:

<select data-val="true" data-val-number="The field SelectedValue must be a number." id="ParentDropDown_SelectedValue" name="ParentDropDown.SelectedValue"> 

Jak dodać atrybuty do własnych szablonów?

+0

Prawdopodobny duplikat tego: http://stackoverflow.com/questions/2655035/creating-a-selectlistitem-with-disabled-disabled-atrybut – ataravati

+0

Masz rację, on chce tego samego rezultatu końcowego. Nie znalazłem tego. Ale nie podoba mi się odpowiedź tam, ponieważ wydaje się nieco hacky też. Zamierzam dać odpowiedź Danielowi J. G., ponieważ wygląda tak, jak chciałem. – Inrego

Odpowiedz

27

Masz rację, te atrybuty (a zwłaszcza atrybut nazwy) są krytyczne dla wiązania modelu.

Powiedzmy, że chcesz utworzyć niestandardową pomocnika jak

public static MvcHtmlString CustomHelperFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 

pierwszy można użyć var fieldName = ExpressionHelper.GetExpressionText(expression); uzyskać nazwę pola.

Następnie użyj var fullBindingName = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName);, aby uzyskać pełną nazwę, dbając o zagnieżdżone widoki.

Wreszcie możesz przekształcić to w atrybut id używając var fieldId = TagBuilder.CreateSanitizedId(fullBindingName);.

Więc prosty zwyczaj pomocnik, który tworzy pole tekstowe można zapisać jako:

public static MvcHtmlString CustomHelperFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 
{    
    var fieldName = ExpressionHelper.GetExpressionText(expression); 
    var fullBindingName = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName); 
    var fieldId = TagBuilder.CreateSanitizedId(fullBindingName); 

    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); 
    var value = metadata.Model; 

    TagBuilder tag = new TagBuilder("input"); 
    tag.Attributes.Add("name", fullBindingName); 
    tag.Attributes.Add("id", fieldId); 
    tag.Attributes.Add("type", "text"); 
    tag.Attributes.Add("value", value == null ? "" : value.ToString()); 

    var validationAttributes = html.GetUnobtrusiveValidationAttributes(fullBindingName, metadata); 
    foreach (var key in validationAttributes.Keys) 
    { 
     tag.Attributes.Add(key, validationAttributes[key].ToString()); 
    } 

    return new MvcHtmlString(tag.ToString(TagRenderMode.SelfClosing)); 
} 

Można go używać w widoku jak:

@Html.CustomHelperFor(model => model.ParentDropDown.SelectedValue) 

I będzie produkować następujący kod HTML:

<input id="ParentDropDown_SelectedValue" name="ParentDropDown.SelectedValue" type="text" value="4"> 

Mam nadzieję, że pomoże!

+0

Dzięki! To mi bardzo pomogło. Teraz po prostu muszę dowiedzieć się, jak powiązać bazę danych z właściwością modelu. Mam model reprezentujący całą DropDownList z opcjami i wybraną wartością. Generuję z tego html i potrzebuję databindować wartość do właściwości SelectedValue. Zgaduję, że powinienem sprawdzić nazwę i/lub id, które pasują do tej właściwości. – Inrego

+0

Wyliczyłem to! Dzięki, banda! – Inrego

+0

@Inrego, cieszę się, że to słyszę :) –

Powiązane problemy