2012-12-26 3 views
18

나는 목적을 설명하는 간단한 모델이 있다고 가정EditorFor IEnumerable을 <T>

public class Category 
{ 
    ... 
    public IEnumerable<Product> Products { get; set; } 
} 

보기 :

@model Category 
... 
<ul> 
    @Html.EditorFor(m => m.Products) 
</ul> 

EditorTemplate : 그렇게하지

@model Product 
... 
<li> 
    @Html.EditorFor(m => m.Name) 
</li> 

IEnumerable<Product>에 대한 EditorTemplate을 정의해야하며,에 대해서만 작성할 수 있습니다.모델 및 MVC 프레임 워크는 IEnumerable에 자체 템플릿을 사용할만큼 똑똑합니다. 그것은 내 컬렉션을 반복하고 내 EditorTemplate를 호출합니다.

출력 HTML 나는 결국 내 컨트롤러에 게시 할 수있는이

... 
<li> 
    <input id="Products_i_Name" name="Products[i].Name" type="text" value="SomeName"> 
</li> 

같은 것입니다.

하지만 왜 EditorTemplate을 템플릿 이름으로 정의 할 때 MVC가 트릭을하지 않습니까? 나는 EditorTemplate

@for (int i = 0; i < Model.Products.Count; i++) 
{ 
    @Html.EditorFor(m => m.Products[i], "ProductTemplate") 
} 

IList<Product>에 속성의 유형을 변경 혼자서 컬렉션을 반복하고 전화를해야하는 경우

@Html.EditorFor(m => m.Products, "ProductTemplate") 

는 나에게 가지 더러운 해결 보인다. 이 작업을 수행 할 수있는 다른 방법이 있습니까?

+0

가능한 중복 http://stackoverflow.com/questions/25333332/correct-idiomatic-way-to-use -custom-editor-templates-with-ienumerable-models-in) – GSerg

+0

[이 질문]을 만들기 전에 검색 할 때이 질문을 놓친 것이 확실하지 않습니다. (http://stackoverflow.com/questions/25333332/correct-idiomatic-way- 사용하기 쉬운 커스텀 에디터 템플릿과 ienumerable 모델 인)을 제공합니다. 연대 기적으로 내 질문은이 질문의 사본으로 마감해야하지만 결국 해결 방법이 있기 때문에 다른 방법으로 사용해야한다고 생각합니다. – GSerg

+2

@GSerg, 답변을 공유해 주셔서 감사합니다. 제안 된 해결 방법이 컬렉션을 통한 간단한'for' 루프보다 더 좋다고 말할 수는 없습니다. 미안하지만, 내 질문에 명확하지 않은이 문제에 대한 해결 방법을 찾고있는 것이 아니라 깨끗하고 (나는 희망했다) 이것을 달성하는 유일한 방법. 그렇기 때문에 질문 자체가 매우 유사하더라도 질문에 대한 대답이 내 문제를 해결했다고 말할 수없는 이유입니다. – Zabavsky

답변

13

이 작업을 수행하는 다른 방법은 없습니까?

단순한 대답은 나쁘지 않습니다. 완전히 동의합니다. 그렇지만 프레임 워크 설계자가이 기능을 구현하기로 결정한 것입니다.

그래서 내가하는 일은 규칙에 충실하는 것입니다. 필자는 각 뷰와 부분별로 특정 뷰 모델을 가지고 있기 때문에 컬렉션의 유형과 동일한 방식으로 명명 된 해당 편집기 템플릿을 갖는 것이 중요하지 않습니다.

+0

내가 두려웠다.문제는 일부 관련 뷰에 대해 동일한 ViewModel을 사용해야한다는 것이며 View에 의존하여이 ViewModel을 표시하는 방법에 따라 다릅니다. 하지만 고마워, 대린, 대답은 고마워. – Zabavsky

15

지금, 나는 Darin 9999 맥주 만 빚지고있다.

public static MvcHtmlString EditorForMany<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, IEnumerable<TValue>>> expression, string templateName = null) where TModel : class 
    { 
     StringBuilder sb = new StringBuilder(); 

     // Get the items from ViewData 
     var items = expression.Compile()(html.ViewData.Model); 
     var fieldName = ExpressionHelper.GetExpressionText(expression); 
     var htmlFieldPrefix = html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix; 
     var fullHtmlFieldPrefix = String.IsNullOrEmpty(htmlFieldPrefix) ? fieldName : String.Format("{0}.{1}", htmlFieldPrefix, fieldName); 
     int index = 0; 

     foreach (TValue item in items) 
     { 
      // Much gratitude to Matt Hidinger for getting the singleItemExpression. 
      // Current html.DisplayFor() throws exception if the expression is anything that isn't a "MemberAccessExpression" 
      // So we have to trick it and place the item into a dummy wrapper and access the item through a Property 
      var dummy = new { Item = item }; 

      // Get the actual item by accessing the "Item" property from our dummy class 
      var memberExpression = Expression.MakeMemberAccess(Expression.Constant(dummy), dummy.GetType().GetProperty("Item")); 

      // Create a lambda expression passing the MemberExpression to access the "Item" property and the expression params 
      var singleItemExpression = Expression.Lambda<Func<TModel, TValue>>(memberExpression, 
                       expression.Parameters); 

      // Now when the form collection is submitted, the default model binder will be able to bind it exactly as it was. 
      var itemFieldName = String.Format("{0}[{1}]", fullHtmlFieldPrefix, index++); 
      string singleItemHtml = html.EditorFor(singleItemExpression, templateName, itemFieldName).ToString(); 
      sb.AppendFormat(singleItemHtml); 
     } 

     return new MvcHtmlString(sb.ToString()); 
    } 
[ASP.NET MVC에서 IEnumerable을 모델 사용자 정의 편집기 템플릿을 사용하는 올바른, 관용적 인 방법] (의
+1

이것을 사용하는 방법에 대한 예제를 추가 할 수 있습니까? –

+0

html.ViewData.Model을 검색하는 동안 널 참조 예외가 발생합니다. 모든 단서? –

+1

'@ Html.EditorForMany (x => Model.Products)' –