2013-05-29 2 views
0

사용자가 관리자가 설정 한 항목에 투표 할 수있는 간단한 웹 응용 프로그램을 구축 중입니다. 각 주제에는 예 또는 아니오 스타일 투표 주제와 같은 두 가지 이상의 옵션이있을 수 있습니다. 두 가지 옵션이 있습니다. "무엇이 켄싱턴의 최고 레스토랑입니까?"라는 투표 주제로 사용됩니다. 많은 옵션을 가질 수 있습니다.ASP.NET에서 동적 중첩 컬렉션이있는 ViewModels 바인딩 MVC4 모델 바인더

public class NewTopicVM 
{ 
    [Required] 
    [Display(Name = "Topic Title")] 
    public string TopicTitle { get; set; } 

    [Required] 
    [Display(Name = "Topic Description")] 
    public string TopicDescription { get; set; } 

    [Display(Name = "Topic Image")] 
    public byte[] TopicImage { get; set; } 
    public List<NewOptionVM> TopicOptions { get; set; } 
} 

public class NewOptionVM 
{ 
    public string OptTitle { get; set; } 
    public string OptDescription { get; set; } 
} 

참고 NewTopicVM에서 NewOptionVM 목록 :

여기에 내 현재 뷰 모델이다. 감사 Iko의 대답, 나는 동적으로 생성 된 입력을 바인딩 할 수 있지만, 내 동적으로 생성 된 것들은 어떤 이유로 바인딩되지 않습니다! 이미 표시이 옵션을 가지고 있기 때문에

var index = 1; 

function generateOptMarkup() { 
    var container = $('<div />'); 

    var optionInputsBlock = $('<div />'); 
    optionInputsBlock.addClass('optionInputsBlock'); 

    var inputTitleBlock = $('<div />'); 
    inputTitleBlock.addClass('inputBlock'); 

    var inputDescBlock = $('<div />'); 
    inputDescBlock.addClass('inputBlock'); 

    var optTitleLbl = $('<label />'); 
    optTitleLbl.attr('for', 'TopicOptions_' + ++index + '__OptTitle'); 
    optTitleLbl.text('Option Title'); 

    var optDescLbl = $('<label />'); 
    optDescLbl.attr('for', 'TopicOptions_' + index + '__OptDescription'); 
    optDescLbl.text('Option Description'); 

    var optTitleInpt = $('<input type="text" />'); 
    optTitleInpt.addClass('text-box single-line'); 
    optTitleInpt.attr('name', 'TopicOptions_' + index + '__OptTitle'); 
    optTitleInpt.attr('id', 'TopicOptions_' + index + '__OptTitle'); 
    optTitleInpt.attr('data-val-required', 'The Option Title field is required.'); 
    optTitleInpt.attr('data-val', 'true'); 

    var optDescInpt = $('<input type="text" />'); 
    optDescInpt.addClass('text-box single-line'); 
    optDescInpt.attr('name', 'TopicOptions_' + index + '__OptDescription'); 
    optDescInpt.attr('id', 'TopicOptions_' + index + '__OptDescription'); 
    optDescInpt.attr('data-val-required', 'The Option Description field is required.'); 
    optDescInpt.attr('data-val', 'true'); 

    inputTitleBlock.append(optTitleLbl).append(optTitleInpt); 
    inputDescBlock.append(optDescLbl).append(optDescInpt); 

    optionInputsBlock.append(inputTitleBlock).append(inputDescBlock); 

    container.append(optionInputsBlock); 

    return container.html(); 
} 


$('div.buttons > a').click(function() { 
    $('div.topicOptionsBlock').append(generateOptMarkup()); 
}); 

내가 Index = 1에서 시작 :

다음은 옵션 입력 필드를 생성하는 jQuery 코드입니다. 여기에 스크린 샷입니다 :

enter image description here

은 처음 두 박스가 결합 된 벌금을 얻을 수는 있지만, 동적으로 클릭 한 후 추가되는 세 번째 버튼의 [옵션 추가]하지 않습니다!

내가 뭘 잘못하고 있니? 나는 색인이 올바른지 보장 한 아직 for 루프와 목록을 :(

답변

2

루프를 작동하지 않는 인덱스 및 editorfor를 사용합니다.

// other fields as usual 

For(int i = 0; i < Model.TopicOptions.Count; i++) 
{ 
    @Html.EditorFor(m => m.TopicOptions[i].OptTitle) 
    @Html.EditorFor(m => m.TopicOptions[i].OptDescription) 
} 

MVC의 기본은 지금을 잡을 것 바인딩. 당신이 검사하는 경우 는 HTML MVC는 TopicOptions__0_OptTitle처럼 그래서 그들을 결합하는 몇 가지 형식이있다.

은 액션에 중단 점을 넣고, 모델이 수동으로 작업을 수행 할 필요가 없습니다 완전히 결합되어야한다.

수정 .PartialView에 for 루프 (2 editorFors)의 내부를 넣을 수 있으며, 호출하면 ViewData를 통해 인덱스를 전달할 수 있습니다. 동적으로 새 항목을 추가하는 경우

for(...) 
    @Html.Partial("_NewOption", new ViewDataDictionary { { "index", i } }) 

지금, 당신은 마지막 항목이 새로운 객체 인 상태 목록을 반환하는 작업에 아약스 전화를 걸 수 있습니다. 조치는 색인을 리턴해야하며 이름과 ID가 자동으로 생성 될 때 바인딩이 정상이됩니다. (모든 것을 서버로 보내 삭제할 수도 있습니다.)

id/name 필드를 javascript로 수동으로 처리할지, 서버에서 자동으로 처리할지에 따라 다릅니다.

+0

고마워요. 이코노미 (Iko) 코드는 동적 입력이 아닌 동적 입력을 위해 작동합니다. 업데이트 된 Q를 참조하십시오. – Ciwan

+0

결코 바보입니다. 입력에 대한 내 이름 속성은 다음과 같은 형식이어야합니다 >> TopicOptions [2] .OptTitle' – Ciwan

+1

좋아, 잘 알아 냈어. 객체 목록을 사용하려면 각 항목에 대한 고유 색인이 필요합니다. 증가하는 색인을 추가해야하기 때문에 항목을 동적으로 추가하는 것은 약간 까다 롭습니다. 중간에있는 항목 하나를 삭제하면 색인 (iirc)을 조정해야합니다. – lko