2015-01-27 4 views
-1

나는 다음과 같은 간단한 개체가 :@ Html.ListBoxFor 키 대신 선택한 항목을 반환 할 수 있습니까?

@using (Html.BeginForm("CreateThings", "ThingStorage"){ 
    @Html.ListBoxFor(x => x.SelectedThings, new MultiSelectList(Model.SelectedThings,"ThingId", "ThingName") 
    <input id="thingSelect" type="button" value="<" /> 
    <input id="thingDeselect" type="button" value=">" /> 
    @Html.ListBoxFor(x => x.UnselectedThings, new MultiSelectList(Model.UnselectedThings,"ThingId", "ThingName") 
} 

이 나에게 모델 오류를 줄 것이다 : 내가 현재 가지고하는 것은 이것이다

public class Thing 
{ 
    public int ThingID { get; set; } 
    public string ThingName { get; set; } 
} 

public class WrapperThing 
{ 
    public List<Thing> SelectedThings{ get; set; } 
    public List<Thing> UnselectedThings{ get; set; } 
} 

public class ThingStorageController 
{ 
    [HttpPost] 
    public ActionResult CreateThings(WrapperThing wt) 
     if(ModelState.IsValid){ 
      //Modelstate has binding errors 
     } 
    } 
} 

내가해야 할 것은이 http://jsfiddle.net/timotheus/7JHA4/

같은입니다 게시물에지도 문자열을 객체 유형으로 가져올 수 없다고 말하는 것은 올바른 것입니다. 선택한 객체의 ID 만 다시 전송되기 때문입니다. 개체 목록 자체를 다시 게시 할 수있는 방법이 있습니까?

오, 보너스 질문으로 대답에서 이것을 고려해보십시오. 실제로 선택한 목록뿐만 아니라 각 목록의 전체 내용을 게시하고 싶습니다. 아마도 ListBoxFor()는 내가 정말로 원하는 컨트롤이 아니며, 내가 성취하고자하는 것에 대한 더 나은 대안을 제안 할 수 있습니까?

+0

조치 코드를 추가하고보기 코드를 작성하십시오. –

+0

나는 이미 분명하다고 생각하지만 어쨌든 조치를 추가하고 양식 코드를 보았습니다. – EvilWeebl

+0

왜 그걸 원하니? 선택한 ID를 다시 게시하고 컨트롤러에 원래 컬렉션을 가져 와서 비교를 수행합니다 (컬렉션을 나타내는 많은 숨겨진 입력을 렌더링 한 다음 모두를 변경하지 않고 게시하면 성능이 저하됩니다). WebForms에서 ViewState를 모방하려고합니다. –

답변

1

SelectedThingsUnselectedThings을 래퍼 인스턴스에 매핑하는 사용자 정의 모델 바인더를 구현할 수 있습니다. 그러나 래퍼 모델의 일부가 아닌 모든 것을 게시하고 싶을 수도 있습니다. 그러므로 나는 이것을 간단하게하려고 노력할 것이다. 모든 것을 제출하려면 매개 변수 int[] SelectedThings, int[] UnselectedThings

[HttpPost] 
public ActionResult Submit(int[] SelectedThings, int[] UnselectedThings) 
{ 
    ... your code ... 
} 

에 동의해야합니다 포스트를 수신

ActionResult, 당신은 세 번째 selectSelectedThingsUnselectedThings에서 모든 옵션을 다시 채워 것 ID AllThings (아마도 style="display:none" 포함)로 구현할 수있다 . 폼의 submit 이벤트 중에 백필이 실행될 수 있습니다.

$('form').submit(function() { 
    $('#SelectedThings option').appendTo('#AllThings'); 
    $('#UnselectedThings option').appendTo('#AllThings'); 
} 

사용자 정의 모델 바인더를 구현하려는 경우, this post

에서 봐, 그리고 당신이 게시물을 따르는 경우에, 나는 DefaultModelBinder에서 상속하는 것이 좋습니다. 여기에 당신을 시작할 수있는 대략적인 예가 있습니다.

public class ThingModelBinder: DefaultModelBinder 
{ 
    private List<Thing> ThingsData = new List<Thing> { new Thing { ThingId = 1, ThingName = "One" }, new Thing { ThingId = 2, ThingName = "Two" } }; 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     //This assumes some persistance layer ThingsData 
     //NOTE: you'll definately need to refactor this, but it should be enough to get you started 
     if (bindingContext.ModelType == typeof(WrapperThing)) 
     { 
      HttpRequestBase request = controllerContext.HttpContext.Request; 

      //convert string to string[] 
      string[] selected = request.Form.Get("SelectedThings").Split(Convert.ToChar(",")).ToArray<string>(); 
      // do the same with unselected 


      //convert sting[] to int[] 
      var iselected = (from i in selected select Convert.ToInt32(i)).ToArray<int>(); 
      // do the same with unselected 

      //fill selected things 
      List<Thing> fillSelected = (from data in ThingsData where iselected.Contains(data.ThingId) select data).ToList<Thing>(); 
      // do the same with unselected 


      //instantiate WrapperThing and populate 
      WrapperThing wrapper = new WrapperThing { SelectedThings = new List<Thing>(), UnselectedThings = new List<Thing>() }; 
      wrapper.SelectedThings = fillSelected; 
      // you guessed it, do the same with unselected 

      return wrapper; 
     } 

     return base.BindModel(controllerContext, bindingContext); 
    } 
} 

게시물에 명시된대로 모델 바인더를 적절한 위치에 등록하십시오.

+0

시작하기가 명확하지 않은 것에 대해 사과드립니다. 액션 메서드로 코드를 업데이트하여 래퍼 객체를 찾고 있음을 보여줍니다 (래퍼가 의심 할 여지없이 다른 속성을 가짐). 그래서 선택 목록에있는 객체에 int (ID) 배열을 원하지 않기 때문에 문제가 발생합니다. 객체 자체를 원합니다. 어떤 생각이라도 이걸 어떻게 얻을 수 있니? – EvilWeebl

+0

대체 방법으로 답변이 업데이트되었습니다. 접근 방식은 게시물에 설명 된 예제를 따릅니다. – RyanCJI

+0

노력에 감사하지만 여전히 저장소 ID와 일치해야하는 지점을 게시하는 경우 (이 경우 "ThingsData"). 개체에서 속성을 표시하는 목록 상자를 가져 오지만 해당 개체의 지정된 키 필드 대신 게시 할 값으로 개체 자체를 유지하는 컨트롤이나 방법이있을 것으로 기대하고 있습니다. – EvilWeebl