ASP.NET MVC 양식에서 확인란을 처리하는 방법은 무엇입니까?


246

주의 :이 질문은 9 세 이상입니다!

가장 좋은 방법은 최신 질문을 검색하거나 특정 버전의 MVC를 찾는 아래의 답변을 검색하는 것입니다. 여기서 많은 답변이 더 이상 사용되지 않습니다.

사용중인 버전에 맞는 답변을 찾으면 사용중인 MVC 버전이 답변에 포함되어 있는지 확인하십시오.
(원래 질문은 아래에서 시작합니다)


이것은 나에게 약간 기괴한 것처럼 보이지만 내가 알 수있는 한, 이것이 당신이하는 방법입니다.

개체 모음이 있으며 사용자가 하나 이상의 개체를 선택하기를 원합니다. 이것은 나에게 "체크 박스와 양식"이라고 말합니다. 내 객체에는 "선택된"개념이 없습니다 (wcf 호출을 직렬화 해제하여 생성 된 기본적인 POCO입니다). 그래서 나는 다음을 수행합니다.

public class SampleObject{
  public Guid Id {get;set;}
  public string Name {get;set;}
}

보기에서 :

<%
    using (Html.BeginForm())
    {
%>
  <%foreach (var o in ViewData.Model) {%>
    <%=Html.CheckBox(o.Id)%>&nbsp;<%= o.Name %>
  <%}%>
  <input type="submit" value="Submit" />
<%}%>

그리고 컨트롤러에서 이것이 사용자가 확인한 객체를 파악할 수있는 유일한 방법입니다.

public ActionResult ThisLooksWeird(FormCollection result)
{
  var winnars = from x in result.AllKeys
          where result[x] != "false"
          select x;
  // yadda
}

처음에는 이상하고 사용자가 확인한 항목의 경우 FormCollection의 값이 true가 아니라 "true false"로 표시됩니다.

분명히, 나는 무언가를 놓치고있다. 나는 이것이 html 양식 내에서 작동하는 컬렉션의 객체가 다음을 사용하여 업데이트된다는 생각을 염두에두고 작성되었다고 생각합니다.UpdateModel() 가 ModelBinder를 하거나 ModelBinder를 통해 .

그러나 내 객체는 이것을 위해 설정되지 않았습니다. 이것이 이것이 유일한 방법이라는 것을 의미합니까? 다른 방법이 있습니까?


2
다른 사람들은이 솔루션이 유용하다고 생각할 것입니다 : stackoverflow.com/questions/3291501/…
Aaron

답변:


262

Html.CheckBox가 이상한 일을하고 있습니다. 결과 페이지에서 소스를 보면 <input type="hidden" />각 확인란과 함께 각 양식 요소에 대해 표시되는 "true false"값을 설명하는 내용이 표시됩니다.

방금 시도한 ASP.NET MVC 베타에서 작동하는 이것을 사용해보십시오.

Html.CheckBox ()를 사용하는 대신 이것을 뷰에 넣으십시오.

<% using (Html.BeginForm("ShowData", "Home")) {  %>
  <% foreach (var o in ViewData.Model) { %>
    <input type="checkbox" name="selectedObjects" value="<%=o.Id%>">
    <%= o.Name %>
  <%}%>
  <input type="submit" value="Submit" />
<%}%>

확인란이 모두 selectedObjects이고value 각각의 체크 박스는 해당 개체의 GUID입니다.

그런 다음 다음 컨트롤러 작업 (또는 Response.Write () 대신 유용한 것을 수행하는 유사한 작업)에 게시하십시오.

public ActionResult ShowData(Guid[] selectedObjects) {
    foreach (Guid guid in selectedObjects) {
        Response.Write(guid.ToString());
    }
    Response.End();
    return (new EmptyResult());
}

이 예는 선택한 상자의 GUID를 작성합니다. ASP.NET MVC는 선택한 확인란의 GUID 값을 Guid[] selectedObjects매개 변수 로 매핑하고 Request.Form 컬렉션의 문자열을 인스턴스화 된 GUID 개체로 구문 분석합니다.


예! 이것이 내 응용 프로그램에서도해야했던 일입니다!
Adhip Gupta

70
wtf. SAME 이름을 컨트롤로 사용하여 숨겨진 입력 필드 ViewState 2.0!
Simon_Weaver

3
이것은 1.0 릴리스에도 있습니다. @ andrea-balducci가 제출 한 답변을 통해 지능적으로 처리 할 수 ​​있습니다. 확인란을 선택하지 않으면 검색된 결과 텍스트는 '거짓 거짓'이어야합니다. 이는 뇌사 브라우저를 설명하기위한 좋은 해결 방법입니다.
Bryan Rehbein

77
놀라다? WTF? 숨겨진 입력은 확인란과 이름이 같습니다. 같은 이름의 확인란을 선택하지 않으면 해당 값이 게시되지 않지만 숨겨진 값은 게시됩니다. 브라우저가 명명 된 요소를 처음 발견하면 해당 값을 사용하고 동일한 이름을 가진 다른 모든 요소를 ​​무시합니다. 이를 통해 값이 제출됩니다. 확인란이 선택되어 있으면 (숨겨진 요소 위에 있다고 가정) true, 확인란이 선택되어 있지 않으면 거짓 (빈 확인란이 무시되고 숨김이 폴 백이 됨). 진짜 wtf는 아무도 이것을 지적하지 않은 이유입니다.
nerraga

19
@nerraga : 당신이 틀렸다 : 같은 이름을 가진 여러 개의 form 요소를 갖는 것이 유효한 html이다; 그렇다면 모든 요소가 게시되고 실제로 주문이 실제로 정의되어 있는지 확실하지 않습니다. "false"라는 단어를 값으로 사용하는 것은 다소 오해의 소지가 있으므로 WTF입니다. 더 나은, 오해의 소지가 적은 선택은 "존재"또는 대시와 같은 의미없는 토큰 일 것입니다.
Eamon Nerbonne

95

HtmlHelper는 숨겨진 입력을 추가하여 컨트롤러에 확인되지 않은 상태를 알려줍니다. 올바른 상태를 확인하려면 다음을 수행하십시오.

bool bChecked = form[key].Contains("true");

1
이것은이 문제에 대한 가장 쉬운 접근법이며 항상 사용합니다. 도우미 메서드를 사용하고 ASP.NET MVC 동작을 설명 할 수 있습니다.
Nick Daniels

8
.. 또는 확인되지 않은 경우 : bool bChecked = form [key] .Equals ( "false"); true 값이 "true, false"이므로 .Contains ( "false")를 수행 할 수 없습니다.
마크 로빈슨

54

왜 그들이 왜 확인란과 같은 이름으로 숨겨진 필드를 넣었는지 궁금해하는 이유는 다음과 같습니다.

소스 코드의 주석 MVCBetaSource \ MVC \ src \ MvcFutures \ Mvc \ ButtonsAndLinkExtensions.cs

<input type="hidden".../>확인란을 추가 로 렌더링합니다 . 이 확인란은 선택하지 않은 확인란이 요청에 전송되지 않는 시나리오를 해결합니다. 숨겨진 입력을 보내면 요청이 제출되었을 때 해당 확인란이 페이지에 있음을 알 수 있습니다.

나는 컨트롤러 액션 메소드의 매개 변수에 바인딩하기 위해 이것을 알아야 할 것으로 생각합니다. 그런 다음 3 상태 부울을 가질 수 있습니다 (nullable bool 매개 변수에 바인딩 됨). 나는 그것을 시도하지 않았지만 그들이 한 일을 바라고 있습니다.


4
네, 그리드 등을 페이징하고 일부 비즈니스 오브젝트에서 이전에 선택된 항목을 선택 취소하려는 시나리오에 유용합니다.
RichardOD

49

또한 <label for="checkbox1">Checkbox 1</label>사람들은 레이블 자체뿐만 아니라 확인란 자체를 클릭 할 수 있기 때문에 사용해야 합니다. 또한 스타일 지정이 쉽고 IE에서는 페이지 컨트롤을 탭하면 강조 표시됩니다.

<%= Html.CheckBox("cbNewColors", true) %><label for="cbNewColors">New colors</label>

이것은 단지 '오 내가 할 수있는'일이 아닙니다. 사용자 경험이 크게 향상되었습니다. 모든 사용자가 아는 것은 아니지만 많은 사용자는 레이블을 클릭 할 수 있습니다.


27

이 답변 중 내장 MVC 기능을 사용하지 않은 것에 놀랐습니다.

나는 이것에 관한 블로그 게시물을 여기 에 썼다. 실제로 라벨을 체크 박스에 연결한다. EditorTemplate 폴더를 사용하여 깔끔하고 모듈 방식으로이 작업을 수행했습니다.

EditorTemplate 폴더에 다음과 같은 새 파일이 생깁니다.

@model SampleObject

@Html.CheckBoxFor(m => m.IsChecked)
@Html.HiddenFor(m => m.Id)
@Html.LabelFor(m => m.IsChecked, Model.Id)

실제보기 에서이 코드를 반복 할 필요가 없습니다. 단순히 한 줄의 코드 :

@Html.EditorFor(x => ViewData.Model)

자세한 내용은 내 블로그 게시물 을 방문 하십시오.


1
감사합니다! Everboyd는 여전히 구식 방식을 사용합니다. 제출할 때이 컬렉션과 request.form 가비지없이 모델에 액세스 할 수 있습니다. 이것이 내가 찾던 것입니다. +1그리고 + 맥주
Piotr Kula

2
이것이 질문에 대한 최고 답변이어야합니다. 매우 간단하고 구현하기 쉽습니다.
요한구나 완

이 답변을 찾기 전에 한동안 우아한 해결책을 찾기 위해 고심했습니다. 몇 년 전이지만 2016 년에도 여전히 완벽하게 유효합니다! 여러 경우에 사용하는 경우 내장 SelectListItem을 이에 적합한 일반 유형으로 사용하십시오
Phil

SampleObject가 목록입니까? @ModelType List (Of Type)
JoshYates1980

25

여기 내가 한 일이 있습니다.

전망:


<input type="checkbox" name="applyChanges" />

제어 장치:


var checkBox = Request.Form["applyChanges"];

if (checkBox == "on")
{
...
}

어떤 경우에는 Html. * 도우미 메서드가 그다지 유용하지 않다는 것을 알았고 평범한 오래된 HTML로 처리하는 것이 좋습니다. 이것은 그들 중 하나이고, 떠오르는 다른 하나는 라디오 버튼입니다.

편집 : 이것은 미리보기 5에 있으며, 분명히 버전간에 YMMV입니다.


1
다른 예제를 추가하고 싶습니다. Object.Property =! String.IsNullOrEmpty (Request.Form [ "NAME"]);
Gup3rSuR4c는

체크하지 않으면 예외로 넘어갑니다
Xulfee

10

첫 번째 값만 읽는 것으로 보이므로 확인란을 선택하면 "true"이고 숨겨진 값만 포함 된 경우 "false"입니다. 이것은 다음과 같은 코드로 쉽게 가져올 수 있습니다.

model.Property = collection["ElementId"].ToLower().StartsWith("true");

8

@Dylan Beattie 위대한 찾기! 정말 감사합니다 더 확장하기 위해이 기법은 모델보기 접근 방식과 완벽하게 작동합니다. MVC는 매우 멋지다. Guid의 배열을 View에 바인딩 된 Model 객체와 같은 이름으로 속성에 바인딩 할 수있다. 예:

뷰 모델 :

public class SampleViewModel
{
    public IList<SampleObject> SampleObjectList { get; set; }
    public Guid[] SelectedObjectIds { get; set; }

    public class SampleObject
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }
}

전망:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Sample View</h2>
<table>
    <thead> 
        <tr>
            <th>Checked</th>
            <th>Object Name</th>
        </tr>
    </thead> 
<% using (Html.BeginForm()) %>
<%{%>                    
    <tbody>
        <% foreach (var item in Model.SampleObjectList)
           { %>
            <tr>
                <td><input type="checkbox" name="SelectedObjectIds" value="<%= item.Id%>" /></td>
                <td><%= Html.Encode(item.Name)%></td>
            </tr>
        <% } %>
    </tbody>
</table>
<input type="submit" value="Submit" />
<%}%>                    

제어 장치:

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult SampleView(Guid id)
    {
        //Object to pass any input objects to the View Model Builder 
        BuilderIO viewModelBuilderInput = new BuilderIO();

        //The View Model Builder is a conglomerate of repositories and methods used to Construct a View Model out of Business Objects
        SampleViewModel viewModel = sampleViewModelBuilder.Build(viewModelBuilderInput);

        return View("SampleView", viewModel);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult SampleView(SampleViewModel viewModel)
    {
        // The array of Guids successfully bound to the SelectedObjectIds property of the View Model!
        return View();
    }

View Model 철학에 익숙한 사람은 기뻐할 것입니다. 이것은 챔피언처럼 작동합니다!


감사합니다. SampleViewModel은 원래 답변에서 약간의 혼란을 해결했습니다.
의회

6

또한 각 확인란의 이름을 다른 이름으로 지정할 수 있으며 해당 이름을 actionresults 매개 변수의 일부로 지정할 수 있습니다.

예,

전망:

 <%= Html.CheckBox("Rs232CheckBox", false, new { @id = "rs232" })%>RS-232

 <%= Html.CheckBox("Rs422CheckBox", false, new { @id = "rs422" })%>RS-422

제어 장치:

public ActionResults MyAction(bool Rs232CheckBox, bool Rs422CheckBox) {
    ...
}

이름이 동일하므로보기의 값이 조치에 전달됩니다.

이 솔루션이 프로젝트에 이상적이지 않다는 것을 알고 있지만 아이디어를 버릴 것이라고 생각했습니다.


5
<input type = "checkbox" name = "checkbox1" /> <label> Check to say hi.</label>

컨트롤러에서 :

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(FormCollection fc)
    {

         var s = fc["checkbox1"];

         if (s == "on")
         {
             string x = "Hi";
         }
    }

4

이 문제는 릴리스 1.0에서도 발생합니다. Html.Checkbox ()는 원래 확인란과 동일한 이름 / ID로 다른 숨겨진 필드를 추가합니다. 그리고 document.GetElemtentsByName ()을 사용하여 확인란 배열을로드하려고 할 때 상황이 어떻게 엉망인지 추측 할 수 있습니다. 기괴하다.


4

내가 수집 할 수있는 것으로부터, 모델은 checked = true 또는 false인지 추측하지 않으려 고, 다음과 같은 양식을 제출하기 전에 jQuery를 사용하여 checkbox 요소에 value 속성을 설정 하여이 문제를 해결했습니다.

 $('input[type="checkbox"]').each(function () {
       $(this).attr('value', $(this).is(':checked'));
 }); 

이렇게하면 확인란의 값을 저장하기 위해 숨겨진 요소가 필요하지 않습니다.


4

이 질문은 MVC3가 나오지 않았을 때 작성되었지만이 질문에 와서 MVC3을 사용하는 사람에게는 "올바른"방법이 필요할 수 있습니다.

전체를하는 것 같아요

Contains("true");

일이 훌륭하고 깨끗하며 모든 MVC 버전에서 작동하지만 문제는 문화가 고려되지 않는다는 것입니다 (실제로 부울의 경우 중요 함).

최소한 MVC3에서 부울 값을 계산하는 "올바른"방법은 ValueProvider를 사용하는 것입니다.

var value = (bool)ValueProvider.GetValue("key").ConvertTo(typeof(bool));

권한을 편집 할 때 클라이언트 사이트 중 하나에서이 작업을 수행합니다.

var allPermissionsBase = Request.Params.AllKeys.Where(x => x.Contains("permission_")).ToList();
var allPermissions = new List<KeyValuePair<int, bool>>();

foreach (var key in allPermissionsBase)
{
     // Try to parse the key as int
     int keyAsInt;
     int.TryParse(key.Replace("permission_", ""), out keyAsInt);

     // Try to get the value as bool
     var value = (bool)ValueProvider.GetValue(key).ConvertTo(typeof(bool));
}

자, 이것의 장점은 거의 모든 간단한 유형으로 이것을 사용할 수 있으며 문화 (돈, 소수점 등)에 따라 정확하다는 것입니다.

ValueProvider는 다음과 같이 작업을 구성 할 때 사용됩니다.

public ActionResult UpdatePermissions(bool permission_1, bool permission_2)

그러나 이러한 목록을 동적으로 작성하고 값을 확인하려고하면 컴파일 타임에 ID를 알 수 없으므로 즉시 처리해야합니다.


메서드에 FormCollection 매개 변수를 추가하는 대신 Request.Params를 사용하는 이유가 있습니까?
SwissCoder

아무 이유없이, 나는 한 방법으로 다른 방법으로 어떤 이점도 얻지 못합니다.
Dan VanWinkle

1
죄송합니다. 실제로 이유가 있습니다. 방금 코드를 살펴본 결과 5 가지 호출에 대해이 하나의 메소드를 사용하고 있으며 각 메소드에서 FormCollection을 전달하고 싶지 않습니다. 이것은 아무 것도 전달할 필요없이 키를 얻는 가장 쉬운 방법이었습니다.
Dan VanWinkle

예, MVC를 처음 사용합니다. 그리고 일반적으로 FormCollection 대신 형식화 된 Model을 사용하는 것과 마찬가지로 Request.Params 대신 FormCollection을 사용하는 것이 일반적으로 더 나은 곳을 읽었습니다 (실제로는 모델을 사용하고 일반적으로 Request.Params를 사용하지 않는 것이 가장 좋습니다). allPermissions 변수 및 keyAsInt와 같은 다른 코드가 사용되지 않는 것을 알았습니다. 대답 해줘서 고마워.
SwissCoder

3

가장 쉬운 방법은 ...

이름과 값을 설정했습니다.

<input type="checkbox" name="selectedProducts" value="@item.ProductId" />@item.Name

그런 다음 제출하면 확인란의 값을 가져 와서 int 배열에 저장하십시오. 적절한 LinQ 기능. 그게 다야 ..

[HttpPost]
        public ActionResult Checkbox(int[] selectedObjects)
        {
            var selected = from x in selectedObjects
                           from y in db
                           where y.ObjectId == x
                           select y;                   

            return View(selected);
        }

3

nautic20의 답변과 동일하게 ViewModel에서 string / int / enum의 collection 속성과 동일한 이름의 MVC 기본 모델 바인딩 확인란 목록을 사용하십시오. 그게 다야.

그러나 한 가지 문제가 지적되어야합니다. 각 확인란 구성 요소에는 MVC 모델 바인딩에 영향을주는 "Id"를 넣지 않아야합니다.

다음 코드는 모델 바인딩에 작동합니다.

 <% foreach (var item in Model.SampleObjectList)
       { %>
        <tr>
            <td><input type="checkbox" name="SelectedObjectIds" value="<%= item.Id%>" /></td>
            <td><%= Html.Encode(item.Name)%></td>
        </tr>
 <% } %>

다음 코드는 모델에 바인딩되지 않습니다 (차이는 각 확인란에 대해 ID가 할당 됨)

<% foreach (var item in Model.SampleObjectList)
       { %>
        <tr>
            <td><input type="checkbox" name="SelectedObjectIds" id="[some unique key]" value="<%= item.Id%>" /></td>
            <td><%= Html.Encode(item.Name)%></td>
        </tr>
<% } %>

응답을 주셔서 감사합니다,하지만이 질문은 juuuust 조금 오래된. 6 살 정도 사용중인 MVC 버전 을 편집 하고 지정할 수 있습니다 . 최신 버전을 사용하는 사람이라면 누구나이 답변을 찾을 수 있습니다.

나는 두 번째입니다. 고유 한 ID를 제거하면 많은 두통과 치아의
gn 거림

사용중인 MVC 버전은이 문제에 대한 .net MVC 4.0입니다.
ChinaHelloWorld 2016 년

2

이것은 Html.CheckBox (...를 사용할 때 이중 값을 잃어 버린 것입니다.

Replace("true,false","true").Split(',')

4 개의 상자를 체크, 체크, 체크하지 않으면 체크, 참, 거짓, 거짓, 거짓, 참, 거짓을 참, 거짓, 거짓, 참으로 바꿉니다. 내가 필요한 것


0

이런 건 어때?

bool isChecked = false;
if (Boolean.TryParse(Request.Form.GetValues(”chkHuman”)[0], out isChecked) == false)
    ModelState.AddModelError(”chkHuman”, Nice try.”);

0

확인란 HtmlHelper를 사용할 때 게시 된 확인란 양식 데이터를 배열로 사용하는 것이 좋습니다. 나는 왜 다른 방법이 효과가 있는지 알지 못하지만 쉼표로 구분 된 문자열을 가능한 한 배열로 취급하는 것을 선호한다고 생각합니다.

따라서 '확인'또는 실제 테스트는 다음과 같습니다.

//looking for [true],[false]
bool isChecked = form.GetValues(key).Contains("true"); 

잘못된 검사는 다음과 같습니다.

//looking for [false],[false] or [false]
bool isNotChecked = !form.GetValues(key).Contains("true"); 

가장 큰 차이점은 GetValues배열로 반환되므로 사용하는 것입니다.


0

그냥 이것을하십시오 $(document).ready:

$('input:hidden').each(function(el) {
    var that = $(this)[0];
    if(that.id.length < 1 ) {

        console.log(that.id);
        that.parentElement.removeChild(that);

    }
});

2
불행히도, JavaScript가 꺼져있는 사람들 (NoScript 플러그인, 오래된 휴대폰, Lynx ...)의 경우 서버 측에서 이상한 결과를 얻을 수 있습니다
ArIck

0

내 해결책은 다음과 같습니다.

<input type="checkbox"  id="IsNew-checkbox"  checked="checked" />     
<input type="hidden"  id="IsNew" name="IsNew" value="true"  />      
<script language="javascript" type="text/javascript" >     
  $('#IsNew-checkbox').click(function () {    
      if ($('#IsNew-checkbox').is(':checked')) {    
          $('#IsNew').val('true');    
      } else {    
          $('#IsNew').val('false');    
       }    
  });   
</script>  

더 많은 것을 여기에서 찾을 수 있습니다 : http://www.blog.mieten.pl/2010/12/asp-net-mvc-custom-checkbox-as-solution-of-string-was-not-recognized-as-a- 유효한 부울 /


이를 위해 Javascript를 사용할 필요가 없습니다 ... var isChecked = formData [key] .Contains ( "true");
Jammer

0

거의 같은 문제가 있었지만 컨트롤러의 반환 값이 다른 값으로 차단되었습니다.

간단한 해결책을 찾았지만 조금 거친 것 같습니다.

입력 해보십시오 Viewbag.컨트롤러 하고 이제 이름을 지정하십시오.Viewbag.Checkbool

이제보기로 전환하고 이것을 시도하십시오 @Viewbag.Checkbool 컨트롤러에서 값을 얻을 수 있습니다.

내 컨트롤러 매개 변수는 다음과 같습니다.

public ActionResult Anzeigen(int productid = 90, bool islive = true)

내 확인란은 다음과 같이 업데이트됩니다.

<input id="isLive" type="checkbox" checked="@ViewBag.Value" ONCLICK="window.location.href = '/MixCategory/Anzeigen?isLive=' + isLive.checked.toString()" />

0

@mmacaulay 사용하여 bool에 대해 이것을 생각해 냈습니다.

// MVC Work around for checkboxes.
bool active = (Request.Form["active"] == "on");

활성화 된 경우 = true

선택하지 않은 활성 = false

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.