ASP.NET MVC의 EditorFor ()에 대한 HTML 특성


129

왜 HTML 속성을 전달할 수 EditorFor()없습니까? 예를 들어;

<%= Html.EditorFor(model => model.Control.PeriodType, 
    new { disabled = "disabled", readonly = "readonly" }) %>

메타 데이터를 사용하고 싶지 않습니다

업데이트 : 솔루션은보기에서 이것을 호출했습니다.

 <%=Html.EditorFor( model => model.Control.PeriodEndDate, new {Modifiable=model.Control.PeriodEndDateModifiable})%>

사용 ViewData["Modifiable"]나는 익명 객체에 전달 된 입력에 읽기 전용 및 / 또는 비활성화 속성을 추가할지 여부를 결정합니다 일부 뷰 로직을 내 사용자 지정 EditorTemplates / String.ascx에서이 EditorFor()라는 매개 변수 additionalViewData및 속성이있는 편집기 템플릿에 전달된다 ViewData수집.


19
진심으로, 여전히 MVC3에서이 제한은 의미가 없으며 실제로 성가시다. 전 세계 사람들은이 말도 안되는 시간을 보내고 머리를 뽑고 있습니다. 이것을 Microsoft Connect로 전송합니다.
Junior Mayhé


3
그것은 단지 나입니까, 아니면 너무 간단 해야하는 것에 대한 많은 BS처럼 보입니까?
Eric K

[CSS 클래스와 HTML 속성을 가진 EditorFor-Implementation] [1] [1] : stackoverflow.com/questions/12675708/…
FunThom

답변:


96

EditorFor메타 데이터와 함께 작동하므로 html 속성을 추가하려면 언제든지 할 수 있습니다. 또 다른 옵션은 단순히 사용자 정의 템플릿을 작성하고 다음을 사용하는 것입니다 TextBoxFor.

<%= Html.TextBoxFor(model => model.Control.PeriodType, 
    new { disabled = "disabled", @readonly = "readonly" }) %>    

html 속성은 모델의 다른 속성에 따라 다르기 때문에 메타 데이터가 작동하지 않습니다. 즉 도메인 또는 viemodel 논리는 정적 메타 데이터가 아닌 html 속성을 결정해야합니다. 또는 요점을 놓치고 있습니까, 메타 데이터를 동적으로 설정할 수 있습니까?
Typo Johnson

무엇입니까 PeriodType? 단순한 속성 아닌가요? 복잡한 개체 인 경우 속성 의 형식 이름을 ~/Views/ControllerName/EditorTemplates/SomeType.ascx어디에 배치하여 전체 템플릿을 사용자 지정할 수 있습니다 . SomeTypePeriodType
Darin Dimitrov

또한 제안 된 코드는 전체 모델을 특정 속성에 액세스하는 부분 템플릿으로 전달하는 것을 의미합니다. 이는 각 속성에 대한 부분이 있음을 의미합니까?
Typo Johnson

2
나는 지금 당신을 얻는다. <% = Html.EditorFor (model => model.Control.PeriodEndDate, 새 {Modifiable = model.Control.PeriodEndDateModifiable}) %>를 사용하고 내 사용자 정의 EditorTemplates / String.ascx에서 ViewData [ "PeriodEndDateModifiable"]를 사용할 수 있습니다. 감사합니다
Typo Johnson

1
@ JuniorMayhé, 나는 이것을 지루한 한계라고 부르지 않을 것입니다. 더 신중하게 생각하면 이것이 의미가 있음을 이해할 것입니다. 실제로 EditorFor 도우미의 요점은 해당 템플릿을 가질 수 있다는 것입니다. 이 템플릿에는 마크 업이 포함될 수 있습니다. 반드시 단일 요소 일 필요는 없습니다. @class예를 들어 3 개의 div가 포함 된 편집기 템플릿 을 정의하는 것은 절대 의미가 없습니다 . Html.TextBoxFor 도우미를 사용하면이 도우미가 생성하는 항목 인 텍스트 상자를 알 수 있으므로 클래스를 입력 요소에 정의하는 것이 좋습니다.
Darin Dimitrov

115

MVC 5.1 업데이트 는 이제 아래의 접근 방식을 직접 지원하므로 내장 편집기에서도 작동합니다. http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features (좋아하는 생각이 들거나 내 대답을 읽는 경우)

최종 업데이트

자체 편집기 템플릿을 사용하거나 MVC 5.1을 사용하는 경우 내장 편집기에서 직접 아래 접근 방식을 지원합니다.

@Html.EditorFor(modelItem => item.YourProperty, 
  new { htmlAttributes = new { @class="verificationStatusSelect", style = "Width:50px"  } })

그런 다음 템플릿에서 (MVC 5.1의 단순 유형에는 필요하지 않음)

@Html.TextBoxFor(m => m, ViewData["htmlAttributes"])

5
이 새로운 기능은 4 년 전에 제기 된 원래 문제를 완벽하게 해결합니다.
CoderSteve

1
TextBoxFor와 그와 같은 도우미 대신 톤의 사용자 정의 편집기 템플릿을 사용하는 경우 ViewData [...]를 각각에 추가하는 것이 환상적인 아이디어라고는 말할 수 없습니다 ... :(
Alexander

42

MVC 5.1부터는 다음을 수행 할 수 있습니다.

@Html.EditorFor(model => model, new { htmlAttributes = new { @class = "form-control" }, })

http://www.asp.net/mvc/overview/releases/mvc51-release-notes#new-features


위 링크가 죽었습니다. 이것은 MVC 5.1에서 사용할 수 있습니다. 자세한 내용은 다음을 참조하십시오 : asp.net/mvc/overview/releases/mvc51-release-notes#new-features
Alaa Masoud

1
고마워요, 링크도 수정했습니다.
vtforester

2
htmlAttributes를 병합하는 방법?
Bart Calixto

내장 / 기본 EditorFor템플릿 에서만 작동합니다 . 직접 구현하는 경우 AntonK의 답변을 따라야합니다.
mxmissile 2016 년

6

이제 ASP.Net MVC 5.1은이 를 지원합니다.

릴리스 노트에서

이제 EditorFor에서 HTML 속성을 익명 객체로 전달할 수 있습니다.

예를 들면 다음과 같습니다.

@Html.EditorFor(model => model, 
              new { htmlAttributes = new { @class = "form-control" }, })

4

다음은 MVC 5.1 Editor의 html 속성에 대한 VB.Net 코드 구문입니다.

@Html.EditorFor(Function(x) x.myStringProp, New With {.htmlAttributes = New With {.class = "myCssClass", .maxlength="30"}}))

3

그냥 사용하지 않는 이유

@Html.DisplayFor(model => model.Control.PeriodType)

30
한 가지 이유는 DisplayFor가 입력을 렌더링하지 않기 때문에 포스트 백시 값이 손실됩니다.
ProfK April

2
또 다른 이유는 편집기가 현재는 항상 잠겨 있지 않은 특정 시나리오이며 데이터는 편집 할 수 없다는 사실을 알리려고합니다.
미르

2

메타 데이터를 사용하지 않으려면 [UIHint("PeriodType")]속성을 사용하여 속성을 꾸미거나 복잡한 유형 인 경우 아무 것도 장식하지 않아도됩니다. EditorFor는 EditorTemplates 폴더에서 PeriodType.aspx 또는 ascx 파일을 찾아 대신 사용합니다.


감사합니다. 에디터 템플릿의 if / else가 특정 필드에만 필요한 경우
Typo Johnson

나는 당신이 (코드가 아닌) 모델을 변경할 수 없다고 말했지만 UIHint로 직접 장식하는 것은 옵션이 아닙니다.
Darrel Lee

2

오늘은 nullable bool에 바인딩되는 확인란에 대해 동일한 문제로 씨름하고 있으며 내 코드가 아닌 모델을 변경할 수 없으므로이를 처리하는 더 좋은 방법을 찾아야했습니다. 약간의 무차별 적 인 힘이지만 99 %의 경우에 효과가 있습니다. 분명히 각 입력 유형에 대해 유효한 속성을 수동으로 수집해야하지만 확인란에 대해 모두 얻은 것 같습니다.

내 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)

내가 추가 Dictionary<string,string> attribs = new Dictionary<string,string>();하고 attribs.Add("tabindex","16");그 중 하나에 @( )내 페이지의 상단에있는 블록. 그런 다음 @Html.CheckBox("IsActive", Model.IsActive.HasValue ? Model.IsActive : false, attribs)내 페이지에서 오류가 발생했습니다. " 'System.Web.Mvc.HtmlHelper <MyProject.Models.MyObject>'에는 'CheckBox'에 대한 정의가 포함되어 있지 않으며 'System.Web에 가장 적합한 확장 메서드 오버로드가 없습니다. Mvc.InputExtensions.CheckBox (System.Web.Mvc.HtmlHelper, string.bool, object) '에 잘못된 인수가 있습니다 ".
vapcguy

2

여전히 EditorFor를 사용할 수 있습니다. 스타일 / html 속성을 ViewData로 전달하십시오.

@Html.EditorFor(model => model.YourProperty, new { style = "Width:50px" })

EditorFor는 템플릿을 사용하여 렌더링하기 때문에 속성의 기본 템플릿을 재정의하고 스타일 속성을 ViewData로 전달할 수 있습니다.

따라서 EditorTemplate은 다음과 같습니다.

@inherits System.Web.Mvc.WebViewPage<object>

@Html.TextBoxFor(m => m, new { @class = "text ui-widget-content", style=ViewData["style"] })

1
Html.TextBoxFor(model => model.Control.PeriodType, 
    new { @class="text-box single-line"})

당신은 이것처럼 사용할 수 있습니다; 와 동일한 출력 Html.EditorFor및 html 속성을 추가 할 수 있습니다


제외시켰다 TextBoxFor무시에게 어떤 종류의 DisplayFormat당신이 적용을 시도 할 수 있습니다.
Eric K

1

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

모델 특성을 사용하여보기에서 편집기를 호출하십시오.

@Html.EditorFor(Function(m) m.MyTypeProperty, "MyTypeEditor", New {.ControlId = "uniqueId"})

VB 구문을 용서하십시오. 그것이 우리가 굴리는 방식입니다.


1

내 경우에는 추가 속성을받을 수있는 HTML5 숫자 입력 편집기 템플릿을 만들려고했습니다. 더 깔끔한 접근법은 자신의 HTML 도우미를 작성하는 것이지만 이미 .ascx 템플릿이 있으므로이 접근법을 사용했습니다.

<%@ 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])%>
       <% }
   } %> />

이 못생긴 비트는 숫자 형 입력을 생성하고 "속성"키가있는 ViewData Dictionary를 찾습니다. 키 / 값 쌍을 속성으로 추가하여 사전을 반복합니다. ID 속성의 정규식은 관련이 없으며 컬렉션에 사용될 때 일반적으로 밑줄로 이스케이프 할 GetFullHtmlFieldId()대괄호 []가 포함 된 id를 반환 하기 때문에 존재 합니다.

이 템플릿은 다음과 같이 호출됩니다.

Html.EditorFor(m => m.Quantity, "NumberField", new { attributes = new Dictionary<string, string>() { { "class", "txtQuantity" } } }

장황하지만 작동합니다. 템플릿에서 리플렉션을 사용하여 사전을 사용하는 대신 속성 이름을 속성 이름으로 사용할 수 있습니다.


1

ViewData컨트롤러에서를 사용하여 조건 설정

ViewData["Modifiable"] = model.recProcessed;

그런 다음 편집기 템플릿에서이 viewdata를 사용하여 컨트롤의 html 속성을 설정하십시오.

@Html.RadioButton(prefix, li.Value, li.Selected, @ViewData["Modifiable"].ToString().ToLower() == "true" ? (object)new  { @id = li.Value, @disabled = "disabled" } : new { @id = li.Value })

0

MVC 5.1 이상 솔루션 (로컬 HtmlAttributes를 병합하고 EditorTemplates에 정의 됨) :

Shared \ EditorTemplates \ String.cshtml :

@Html.TextBoxFor(model => model, new { @class = "form-control", placeholder = ViewData.ModelMetadata.Watermark }.ToExpando().MergeHtmlAttributes(ViewData["htmlAttributes"].ToExpando()))

확장 :

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

용법:

@Html.EditorFor(m => m.PromotionalCode, new { htmlAttributes = new { ng_model = "roomCtrl.searchRoomModel().promoCode" }})

1
고마워요. 모든 data_xxx 속성을 제외하고, 캐스팅 할 때 _를-로 바꾸어야하는 곳 source1source2as IDictionary<string, object>. 이 기능을 만들었습니다 : private static IDictionary<string, object> ToHtmlAttributesDictionary(this IEnumerable<KeyValuePair<string, object>> dico) { return dico.ToDictionary(s => s.Key.Replace('_', '-'), s => s.Value); }
Marien Monnier
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.