2012-02-03 5 views
21

오랫동안 내 모델의 subcollection을 편집해야했습니다. 모델 컬렉션이 null로되었습니다. Asp : net MVC 3 : @ Html.Editor 템플릿에서 내 모델의 하위 컬렉션?

나는 마침내 해결책을 발견,하지만 난 그것을 조금 더러운 찾을 :

먼저 내 테스트 datas :

모델 객체 :

public class ContainerObject 
    { 
     public String Title { get; set; } 
     public List<ContainedObject> ObjectList { get; set; } 
    } 

하위 컬렉션 개체를 :

public class ContainedObject 
{ 
    public int Id { get; set; } 
    public String Text { get; set; } 
    public Boolean IsSelected { get; set; } 
} 
개체에게

@model WebTestApplication.Models.ContainerObject 

@{ 
    ViewBag.Title = "TestForm"; 
} 
@using (Html.BeginForm("TestFormResult","Home", FormMethod.Post)){ 
    @Html.EditorFor(x => x.Title) 
    Html.RenderPartial("ContainedObject", Model.ObjectList); 
    <input type="submit" value="Submit"/> 
} 

부분 V 편집 객체

[HttpPost] 
    public ActionResult TestFormResult(ContainerObject filledObject) 
    { 
     return View(); 
    } 

을보기를 수신

public ActionResult TestForm() 
    { 
     return View(new ContainerObject() 
     { 
      Title = "This is a sample title", 
      ObjectList = new List<ContainedObject>() 
       { 
        new ContainedObject(){Id=1, IsSelected = true, Text="ObjectOne"}, 
        new ContainedObject(){Id=2, IsSelected = false, Text="ObjectTwo"}, 
        new ContainedObject(){Id=3, IsSelected = true, Text="ObjectThree"}, 
        new ContainedObject(){Id=4, IsSelected = false, Text="ObjectFour"}, 
       } 
     }); 
    } 

컨트롤러를 생성

컨트롤러 메소드 iew (ContainedObject.cshtml)

@model IEnumerable<WebTestApplication.Models.ContainedObject> 
@{ 
    ViewBag.Title = "ContainedObject"; 
    int i = 0; 
} 
@foreach (WebTestApplication.Models.ContainedObject currentObject in Model) 
{ 
    <br /> 
    @Html.Label(currentObject.Text); 
    @Html.CheckBox("ObjectList[" + i + "].IsSelected", currentObject.IsSelected);                          
    @Html.Hidden("ObjectList[" + i + "].Id", currentObject.Id);                         
    @Html.Hidden("ObjectList[" + i + "].Text", currentObject.Text); 
    i++; 
} 

이 실제로 작동하고,하지만 한 가지 문제했습니다 : 나는 이름 나 자신을 생성하고 컨테이너 객체의 속성을 지정했습니다

보기에서 Html.RenderPartial 대신 Html.EditorFor을 사용하려고했는데 문제는 그 이름이 "ObjectList. [0] .Id"(추가로. 속성 이름과 접근 자 사이).

또한 부분 뷰에서 @ Html.EditorFor 만 사용하려고했지만 객체의 이름과 함께 vars를 만듭니다.

@model WebTestApplication.Models.ContainerObject 

@{ 
    ViewBag.Title = "TestForm"; 
} 
@using (Html.BeginForm("TestFormResult", "Home", FormMethod.Post)) 
{ 
    @Html.EditorFor(x => x.Title) 
    for (int i = 0; i < Model.ObjectList.Count; i++) 
    { 
     <br /> 
     @Html.Label(Model.ObjectList[i].Text); 
     @Html.CheckBoxFor(m => Model.ObjectList[i].IsSelected); 
     @Html.HiddenFor(m => Model.ObjectList[i].Id); 
     @Html.HiddenFor(m => Model.ObjectList[i].Text); 
    } 

    <br /><input type="submit" value="Submit"/> 
} 

그러나 여기 간단한 템플릿,하지만 진짜 내 경우에는 내가 훨씬 더 많은 데이터를해야합니다, 이것은 다시 사용됩니다 : 나는 어떤 템플릿을 사용하지 않는 경우

, 그것은 작동 여러 번. 그래서 최선의 선택은 무엇입니까?

답변

38

EditorTemplate을 도입하여 코드를 단순화 할 수 있습니다. 우리가 EditorFor으로 RenderPartial 교체를 제외하고

  • 메인 뷰가 거의 동일하게 유지 : 여기 어떻게

TestForm.cshtml

@model WebTestApplication.Models.ContainerObject 

@{ 
    ViewBag.Title = "TestForm"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 

@using (Html.BeginForm("TestFormResult", "Home", FormMethod.Post)) { 
    @Html.EditorFor(m => m.Title) 
    @Html.EditorFor(m => m.ObjectList); 

    <input type="submit" value="Submit" /> 
} 
  • 그런 EditorTemplates에서보기/홈라는 이름의 폴더를 생성 (가정 컨트롤러를 홈입니다) :

enter image description here

  • 하고 다음을 추가 템플릿은 ContainedObj 용입니다. 요법 :

ContainedObject.cshtml

@model WebTestApplication.Models.ContainedObject 

<p> 
    @Html.DisplayFor(m => m.Text) 
    @Html.CheckBoxFor(m => m.IsSelected) 
    @Html.HiddenFor(m => m.Id) 
    @Html.HiddenFor(m => m.Text) 
</p> 

이 편집기는 자동으로 각 뷰를 렌더링 객체의 목록을 반복합니다. 희망이 도움이됩니다.

+1

놀라운! 목록 인 경우 editorFor 또는 DisplayFor가 자동으로 반복되는 것을 알지 못했습니다! 그것을 사용하는 템플릿을 지정할 때 작동하게하는 방법이 있습니까? – J4N

+0

같은 컨트롤러 (예 : 선택한 값과 기본값)에서 확인란 (여러 선택) 또는 라디오 버튼 (한 항목 선택)을 사용하여 표시 할 수있는 몇 가지 정보가 여러 번 있기 때문에 지정할 수 있습니다. – J4N

+0

지정하려고합니다 다른 템플릿? 그렇다면 템플릿 이름을 허용하는 EditorFor에 대한 오버로드가 있습니다. –

5

다른 관련 항목을 찾고있는 동안이 스레드를 발견했습니다. 데니스는 정답을 가지고 있지만, 다른 사람들이이 문제를 겪을 경우를 대비해 일부 구문을 추가 할 것을 생각했습니다.

"SomeTemplate.cshtml"이라는 편집기 템플릿이있는 경우 다음과 같이 Item 목록에 사용할 수 있습니다. 보기 : 편집기 템플릿에서 다음

@for (var i = 0; i < Model.ObjectList.Count(); i++) 
{ 
    @Html.EditorFor(m => m.ObjectList[i], "SomeTemplate") 
} 

:

@model WebTestApplication.Models.ContainedObject 

<br /> 
@Html.Label(Model.Text); 
@Html.CheckBoxFor(m => m.IsSelected); 
@Html.HiddenFor(m => m.Id); 
@Html.HiddenFor(m => m.Text); 
관련 문제