2011-02-03 2 views
12

모델에서 포스트 백이 발생할 때 체크 박스 목록 항목 목록을 쉽고 빠르게 바인딩 할 수있는 방법을 찾으려면 여기를 참조하십시오.체크 박스 목록을 asp.net mvc의 모델에 바인딩하는 방법이 있습니까

분명히 지금하는 일반적인 방법은 다음과 같이하는 것 같습니다. form.GetValues("checkboxList")[0].Contains("true"); 고통스럽고 정확하지는 않은 것 같습니다.

의 내부에 IList<string> 또는 string[]을 채우는 것 (또는 뷰에서 도우미없이 생성되는) 체크 박스의 목록이나 UpdateModel(myViewModel, form.ToValueProvider()); 단계에서 심지어 그 데이터의 배열 문제를 결합하는 방법이 있나요 모델?

답변

9

당신은 모델을 시작할 수 :

public class MyViewModel 
{ 
    public int Id { get; set; } 
    public bool IsChecked { get; set; } 
} 

다음 컨트롤러 :

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var model = new[] 
     { 
      new MyViewModel { Id = 1, IsChecked = false }, 
      new MyViewModel { Id = 2, IsChecked = true }, 
      new MyViewModel { Id = 3, IsChecked = false }, 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Index(IEnumerable<MyViewModel> model) 
    { 
     // TODO: Handle the user selection here 
     ... 
    } 
} 

뷰 (~/Views/Home/Index.aspx) :

<% using (Html.BeginForm()) { %> 
    <%=Html.EditorForModel() %> 
    <input type="submit" value="OK" /> 
<% } %> 

그리고 마지막으로 해당 편집기 템플릿 :

<%@ Control 
    Language="C#" 
    Inherits="System.Web.Mvc.ViewUserControl<AppName.Models.MyViewModel>" %> 
<%= Html.HiddenFor(x => x.Id) %> 
<%= Html.CheckBoxFor(x => x.IsChecked) %> 

이제 POST 동작에서 양식을 제출하면 선택된 값 목록이 해당 ID와 함께 표시됩니다.

+0

아이디어가 나쁘지는 않지만이 아닌 다른 항목 양식을 사용할 때 작동하지 않습니다 :

그리고 마지막으로는, 양식을 처리 할 수있는 액션은 제출합니다. 예를 들어 사용자 이름/비밀번호 + 확인란 모음이 있다고하면 작동하지 않습니다./ – Erick

+2

@Erick 물론 작동 할 수 있습니다. 뷰 모델에는'Username'과'Password'와 같은 간단한 속성과 체크 박스 정보를 포함 할 컬렉션 속성 인 IEnumerable 가 포함됩니다. 이제 폼에서'Html.EditorForModel'을 사용하는 대신 간단한'<% = Html.TextBoxFor (x => x.Username) %>'와'<% = Html.PasswordFor (x => x.Password) %>와 같은 편집기 템플릿을 렌더링하는 <% = Html.EditorFor (x => x.MyCheckboxes) %>'를 사용합니다. –

+0

나는 이것을 성취하는 많은 방법을 읽었으며 이것은 가장 우아한 해결책이었다. 감사! – JimDaniel

9

다음은 빠르고 쉬운 방법입니다. checkbox 입력 요소 안에 value 속성을 설정하고 모두 동일하게 name을 지정하면됩니다. 당신의 컨트롤러에서

<% using (Html.BeginForm()) { %> 
    <p><input type="checkbox" name="checkboxList" value="Value A" /> Value A</p> 
    <p><input type="checkbox" name="checkboxList" value="Value B" /> Value B</p> 
    <p><input type="checkbox" name="checkboxList" value="Value C" /> Value C</p> 
    <p><input type="checkbox" name="checkboxList" value="Value D" /> Value D</p> 
    <p><input type="checkbox" name="checkboxList" value="Value E" /> Value E</p> 
    <p><input type="checkbox" name="checkboxList" value="Value F" /> Value F</p> 
    <input type="submit" value="OK" /> 
<% } %> 

: 나는 사이트에서 이것을 구현하는 경우 , 내가 필요로 그냥 HTML로보기를 name, valueisChecked 매개 변수이 필요하지만 여기 CheckBox 도우미 메서드를 만들 것

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Index(IEnumerable<string> checkboxList) 
{ 
    if (checkboxList != null) 
    { 
     ViewData["Message"] = "You selected " + checkboxList.Aggregate("", (a, b) => a + " " + b); 
    } 
    else 
    { 
     ViewData["Message"] = "You didn't select anything."; 
    } 

    return View(); 
} 

매개 변수 (사용자가 원하는 경우 IList<string>로 만들 수 있음)에는 선택된 항목의 값만 포함됩니다. 상자를 선택하지 않으면 null이됩니다.

+0

사용자가 체크 박스 – tugberk

+0

@tugberk에 모델을 바인딩하려는 경우 고통이 될 것이므로 기본 HTML 코드를 배치하는 것이 좋지 않다고 생각합니다. 프로덕션 코드에서 도우미 메서드를 사용한다고 말했습니다. 나는 단지 원래의 질문에 대한 답을 보여 주려했다. 도우미 메서드 코드를 추가하겠습니다. – CoderDennis

+2

정답입니다. 내장 된'Html.CheckBox() '도우미를 사용하려고하면 숨겨진 필드를'value = "false"'로 삽입 할 때 ** insist **하게되고, 이는 모델 바인딩을 방해합니다. – Yuck

0

이 꽤 잘 정의 모델 바인더 및 일반 HTML을 ... 사용

먼저, 면도기 구문에 HTML 양식 작품 :

@using (Html.BeginForm("Action", "Controller", FormMethod.Post)) { 
    <ol> 
     <li><input type="textbox" name="tBox" value="example of another form element" /></li> 

     <li><input type="checkbox" name="cBox" value="1" /> One</li> 
     <li><input type="checkbox" name="cBox" value="2" /> Two</li> 
     <li><input type="checkbox" name="cBox" value="3" /> Three</li> 
     <li><input type="checkbox" name="cBox" value="4" /> Four</li> 
     <li><input type="checkbox" name="cBox" value="5" /> Five</li> 

     <li><input type="submit" /></li> 
    </ol> 
} 

(FormMethod.Post.Get 수는 중요하지 않습니다

:

다음)이 대한 적절한 MVC의 의미에서 양식 제출을 나타내는 모델 객체를210

맞춤형 모델 바인더 클래스 (이 모델을 바인딩 된 모델 안에 넣고 싶습니다. 그래서 위에서 만든 모델을 반복하여 추가 할 위치를 보여줍니다.개인 속성 세터를 사용하는 바인더 좋은 일이있다)는 또한 내부에서 허용 걸기

public class CheckboxListExampleModel { 
    public string TextboxValue { get; private set; } 
    public List<int> CheckboxValues { get; private set; } 

    public class Binder : DefaultModelBinder { 
     public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { 
      var model = new CheckboxListExampleModel(); 

      model.TextboxValue = bindingContext.GetValueAsString("tBox"); 

      string checkboxCsv = bindingContext.GetValueAsString("cBox"); 
      // checkboxCsv will be a comma-separated list of the 'value' attributes 
      // of all the checkboxes with name "cBox" which were checked 
      model.CheckboxValues = checkboxCsv.SplitCsv<int>(); 

      return model; 
     } 
    } 
} 

.GetValueAsString() 명확성을 위해 사용되는 확장 방법이며, 여기있다 :

public static string GetValueAsString(this ModelBindingContext context, string formValueName, bool treatWhitespaceAsNull = true) { 
     var providerResult = context.ValueProvider.GetValue(formValueName); 
     if (providerResult.IsNotNull() && !providerResult.AttemptedValue.IsNull()) { 
      if (treatWhitespaceAsNull && providerResult.AttemptedValue.IsNullOrWhiteSpace()) { 
       return null; 
      } else { 
       return providerResult.AttemptedValue.Trim(); 
      } 
     } 
     return null; 
    } 

.SplitCsv<T>()이고 또한 확장 메서드가 있지만 일반적으로 충분히 필요하고 지저분한 코드이므로 독자에게 연습 문제로 남겨 두겠습니다.

[HttpPost] 
public ActionResult Action([ModelBinder(typeof(CheckboxListExampleModel.Binder))] CheckboxListExampleModel model) { 
    // stuff 
} 
관련 문제