Dlaczego nie mogę przekazać atrybutów HTML do EditorFor()
? na przykład;
<%= Html.EditorFor(model => model.Control.PeriodType,
new { disabled = "disabled", readonly = "readonly" }) %>
Nie chcę używać metadanych
Aktualizacja : rozwiązaniem było nazwanie tego z widoku:
<%=Html.EditorFor( model => model.Control.PeriodEndDate, new {Modifiable=model.Control.PeriodEndDateModifiable})%>
i użyj ViewData["Modifiable"]
w moim niestandardowym EditorTemplates / String.ascx, gdzie mam pewną logikę widoku, która określa, czy dodać atrybuty tylko do odczytu i / lub wyłączone do danych wejściowych. Obiekt anonimowy przekazany do EditorFor()
jest parametrem o nazwie, additionalViewData
a jego właściwości są przekazywane do szablonu edytora ViewData
kolekcja.
html
asp.net-mvc
editorfor
Typo Johnson
źródło
źródło
Odpowiedzi:
EditorFor
działa z metadanymi, więc jeśli chcesz dodać atrybuty html, zawsze możesz to zrobić . Inną opcją jest po prostu napisanie własnego szablonu i użycieTextBoxFor
:<%= Html.TextBoxFor(model => model.Control.PeriodType, new { disabled = "disabled", @readonly = "readonly" }) %>
źródło
PeriodType
? Czy to nie jest prosta właściwość? Jeśli jest to złożony obiekt, możesz dostosować cały szablon, umieszczając część w~/Views/ControllerName/EditorTemplates/SomeType.ascx
miejscu, w którymSomeType
znajduje się nazwa typuPeriodType
właściwości.@class
szablonu edytora, który zawiera na przykład 3 elementy div. Helper Html.TextBoxFor pozwala ci to zdefiniować, ponieważ wiesz, co ten helper generuje - pole tekstowe, więc sensowne jest zdefiniowanie klasy jako elementu wejściowego.Aktualizacja MVC 5.1 obsługuje teraz bezpośrednio poniższe podejście, więc działa również w przypadku wbudowanego edytora. http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features (To albo przypadek wspólnego myślenia Wielkiego Umysłu, albo przeczytali moją odpowiedź :)
Zakończ aktualizację
Jeśli używasz własnego szablonu edytora lub MVC 5.1, który obsługuje teraz poniższe podejście bezpośrednio dla wbudowanych edytorów.
@Html.EditorFor(modelItem => item.YourProperty, new { htmlAttributes = new { @class="verificationStatusSelect", style = "Width:50px" } })
następnie w swoim szablonie (niewymagane dla prostych typów w MVC 5.1)
@Html.TextBoxFor(m => m, ViewData["htmlAttributes"])
źródło
Od wersji MVC 5.1 możesz teraz wykonać następujące czynności:
@Html.EditorFor(model => model, new { htmlAttributes = new { @class = "form-control" }, })
http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features
źródło
EditorFor
szablonami. Jeśli wdrażasz własne, musisz postępować zgodnie z odpowiedzią AntonK.Teraz ASP.Net MVC 5.1 ma dla niego wbudowaną obsługę.
Z uwag do wydania
Na przykład:
@Html.EditorFor(model => model, new { htmlAttributes = new { @class = "form-control" }, })
źródło
Oto składnia kodu VB.Net dla atrybutów html w MVC 5.1 EditorFor
@Html.EditorFor(Function(x) x.myStringProp, New With {.htmlAttributes = New With {.class = "myCssClass", .maxlength="30"}}))
źródło
Dlaczego nie po prostu użyć
@Html.DisplayFor(model => model.Control.PeriodType)
źródło
Jeśli nie chcesz używać metadanych, możesz użyć
[UIHint("PeriodType")]
atrybutu do udekorowania właściwości lub jeśli jest to typ złożony, nie musisz niczego dekorować. EditorFor wyszuka plik PeriodType.aspx lub ascx w folderze EditorTemplates i użyje go zamiast tego.źródło
Zmagałem się dzisiaj z tym samym problemem dla pola wyboru, które wiąże się z wartością zerową bool, a ponieważ nie mogę zmienić mojego modelu (nie mojego kodu), musiałem wymyślić lepszy sposób radzenia sobie z tym. To trochę brutalna siła, ale powinna działać w 99% przypadków, które mogę napotkać. Oczywiście musiałbyś ręcznie wypełnić prawidłowe atrybuty dla każdego typu danych wejściowych, ale myślę, że otrzymałem je wszystkie dla pola wyboru.
W moim szablonie edytora Boolean.cshtml:
@model bool? @{ var attribs = new Dictionary<string, object>(); var validAttribs = new string[] {"style", "class", "checked", "@class", "classname","id", "required", "value", "disabled", "readonly", "accesskey", "lang", "tabindex", "title", "onblur", "onfocus", "onclick", "onchange", "ondblclick", "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onselect"}; foreach (var item in ViewData) { if (item.Key.ToLower().IndexOf("data_") == 0 || item.Key.ToLower().IndexOf("aria_") == 0) { attribs.Add(item.Key.Replace('_', '-'), item.Value); } else { if (validAttribs.Contains(item.Key.ToLower())) { attribs.Add(item.Key, item.Value); } } } } @Html.CheckBox("", Model.GetValueOrDefault(), attribs)
źródło
Dictionary<string,string> attribs = new Dictionary<string,string>();
iattribs.Add("tabindex","16");
w jednym z tych@( )
bloków na górze mojej strony. Potem zrobiłem@Html.CheckBox("IsActive", Model.IsActive.HasValue ? Model.IsActive : false, attribs)
na mojej stronie i wyświetla mi się błąd: „„ System.Web.Mvc.HtmlHelper <MyProject.Models.MyObject> ”nie zawiera definicji„ CheckBox ”i przeciążenia najlepszej metody rozszerzenia„ System.Web. Mvc.InputExtensions.CheckBox (System.Web.Mvc.HtmlHelper, string.bool, object) „zawiera nieprawidłowe argumenty”.Nadal możesz używać EditorFor. Po prostu przekaż styl / dowolny atrybut html jako ViewData.
@Html.EditorFor(model => model.YourProperty, new { style = "Width:50px" })
Ponieważ EditorFor używa szablonów do renderowania, możesz zastąpić domyślny szablon dla swojej właściwości i po prostu przekazać atrybut stylu jako ViewData.
Więc Twój EditorTemplate chciałby, aby:
@inherits System.Web.Mvc.WebViewPage<object> @Html.TextBoxFor(m => m, new { @class = "text ui-widget-content", style=ViewData["style"] })
źródło
Html.TextBoxFor(model => model.Control.PeriodType, new { @class="text-box single-line"})
możesz używać w ten sposób; takie same dane wyjściowe
Html.EditorFor
, jak i możesz dodać atrybuty HTMLźródło
TextBoxFor
ignoruje wszelkie rodzajeDisplayFormat
wniosków, które możesz próbować zastosować.Po prostu utwórz własny szablon dla typu w Views / Shared / EditorTemplates / MyTypeEditor.vbhtml
@ModelType MyType @ModelType MyType @Code Dim name As String = ViewData("ControlId") If String.IsNullOrEmpty(name) Then name = "MyTypeEditor" End If End Code ' Mark-up for MyType Editor @Html.TextBox(name, Model, New With {.style = "width:65px;background-color:yellow"})
Wywołaj edytor z widoku z właściwością modelu:
@Html.EditorFor(Function(m) m.MyTypeProperty, "MyTypeEditor", New {.ControlId = "uniqueId"})
Przepraszam za składnię VB. Tak właśnie się toczymy.
źródło
W moim przypadku próbowałem stworzyć szablon edytora wprowadzania liczb HTML5, który mógłby otrzymać dodatkowe atrybuty. Lepszym podejściem byłoby napisanie własnego pomocnika HTML, ale ponieważ mam już swój szablon .ascx, wybrałem następujące podejście:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> <input id="<%= Regex.Replace(ViewData.TemplateInfo.GetFullHtmlFieldId(""), @"[\[\]]", "_") %>" name="<%= ViewData.TemplateInfo.HtmlFieldPrefix %>" type="number" value="<%= ViewData.TemplateInfo.FormattedModelValue %>" <% if (ViewData["attributes"] != null) { Dictionary<string, string> attributes = (Dictionary<string, string>)ViewData["attributes"]; foreach (string attributeName in attributes.Keys){%> <%= String.Format(" {0}=\"{1}\"", attributeName, attributes[attributeName])%> <% } } %> />
Ten brzydki bit tworzy dane wejściowe typu liczbowego i szuka słownika ViewData z kluczowymi „atrybutami”. Będzie iterować przez słownik, dodając swoje pary klucz / wartość jako atrybuty. Regex w atrybucie ID jest niepowiązany i występuje, ponieważ gdy jest używany w kolekcji,
GetFullHtmlFieldId()
zwraca identyfikator zawierający nawiasy kwadratowe,[]
które normalnie byłyby oznaczone jako podkreślenia.Ten szablon nazywa się wtedy następująco:
Html.EditorFor(m => m.Quantity, "NumberField", new { attributes = new Dictionary<string, string>() { { "class", "txtQuantity" } } }
Pełne, ale działa. Prawdopodobnie możesz użyć odbicia w szablonie, aby użyć nazw właściwości jako nazw atrybutów zamiast używania słownika.
źródło
Ustaw warunek za pomocą
ViewData
w kontrolerzeViewData["Modifiable"] = model.recProcessed;
Następnie użyj tego widoku danych w szablonie edytora, aby ustawić atrybut HTML kontrolki
@Html.RadioButton(prefix, li.Value, li.Selected, @ViewData["Modifiable"].ToString().ToLower() == "true" ? (object)new { @id = li.Value, @disabled = "disabled" } : new { @id = li.Value })
źródło
Rozwiązanie MVC 5.1 i nowsze (połączy lokalne HtmlAttributes i zdefiniowane w EditorTemplates):
Shared \ EditorTemplates \ String.cshtml:
@Html.TextBoxFor(model => model, new { @class = "form-control", placeholder = ViewData.ModelMetadata.Watermark }.ToExpando().MergeHtmlAttributes(ViewData["htmlAttributes"].ToExpando()))
Rozszerzenia:
public static IDictionary<string, object> MergeHtmlAttributes(this ExpandoObject source1, dynamic source2) { Condition.Requires(source1, "source1").IsNotNull().IsLongerThan(0); IDictionary<string, object> result = source2 == null ? new Dictionary<string, object>() : (IDictionary<string, object>) source2; var dictionary1 = (IDictionary<string, object>) source1; string[] commonKeys = result.Keys.Where(dictionary1.ContainsKey).ToArray(); foreach (var key in commonKeys) { result[key] = string.Format("{0} {1}", dictionary1[key], result[key]); } foreach (var item in dictionary1.Where(pair => !result.ContainsKey(pair.Key))) { result.Add(item); } return result; } public static ExpandoObject ToExpando(this object anonymousObject) { IDictionary<string, object> anonymousDictionary = new RouteValueDictionary(anonymousObject); IDictionary<string, object> expando = new ExpandoObject(); foreach (var item in anonymousDictionary) expando.Add(item); return (ExpandoObject)expando; } public static bool HasProperty(this ExpandoObject expando, string key) { return ((IDictionary<string, object>)expando).ContainsKey(key); }
Stosowanie:
@Html.EditorFor(m => m.PromotionalCode, new { htmlAttributes = new { ng_model = "roomCtrl.searchRoomModel().promoCode" }})
źródło
source1
isource2
jakoIDictionary<string, object>
. Zrobiłem tę funkcję:private static IDictionary<string, object> ToHtmlAttributesDictionary(this IEnumerable<KeyValuePair<string, object>> dico) { return dico.ToDictionary(s => s.Key.Replace('_', '-'), s => s.Value); }