ASP.NET MVCフォームのチェックボックスを処理する方法は?


246

注意:この質問は9年以上前のものです。

あなたの最良の選択肢は、新しい質問を検索するか、以下の回答を検索して特定のバージョンのMVCを探すことです。

ご使用のバージョンで有効な回答が見つかった場合は、使用しているMVCのバージョンが回答に含まれていることを確認してください。
(元の質問は以下から始まります)


これは少し奇妙に思えますが、私の知る限り、これがあなたのやり方です。

オブジェクトのコレクションがあり、ユーザーにそれらの1つ以上を選択してもらいたい。これは「チェックボックス付きのフォーム」と私に言っています。私のオブジェクトには、「選択された」という概念はありません(これらは、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/...
アーロン・

回答:


262

Html.CheckBoxが奇妙なことをしています-結果のページでソースを表示<input type="hidden" />すると、各チェックボックスの横に生成されていることがわかります。これは、各フォーム要素に表示されている「true false」値を説明しています。

これを試してみてください。私は試したばかりなので、ASP.NET MVC Betaで確実に機能します。

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" />
<%}%>

チェックボックスはすべてと呼ばれselectedObjectsvalue各チェックボックスのは対応するオブジェクトの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。コントロールとして同じ名前の非表示の入力フィールド。そのViewState 2.0!
Simon_Weaver 2009年

3
これは1.0リリースにも含まれています。これに対処するためのインテリジェントな方法を提供する@ andrea-balducciの回答をご覧ください。チェックボックスが
オフの

77
驚き?WTF?非表示の入力はチェックボックスと同じ名前を持っています-同じ名前のチェックボックスがチェックされていない場合、その値は投稿されませんが、非表示の値は投稿されます。ブラウザが名前付き要素に初めて遭遇したとき、その値を使用し、同じ名前の他のすべての要素を無視します。これにより、値が送信されることが保証されます。チェックボックスがチェックされている場合はtrue(非表示要素の上にあると想定)、チェックボックスがオフの場合はfalse(空のチェックボックスは無視され、非表示はフォールバックになります)。本当のwtfは、誰もこれを指摘しなかった理由です。
nerraga 2009

19
@nerraga:間違いです。同じ名前の複数のフォーム要素を持つことは有効な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"); .Contains( "false")の実行は、真の値が "true、false"であるため失敗します。
Mark Robinson、

54

彼らがなぜチェックボックスと同じ名前の隠しフィールドを入れるのか疑問に思っている場合、理由は次のとおりです:

ソースコードMVCBetaSource \ MVC \ src \ MvcFutures \ Mvc \ ButtonsAndLinkExtensions.csからのコメント

<input type="hidden".../>チェックボックスの追加をレンダリングします。これは、チェックされていないチェックボックスがリクエストで送信されないシナリオに対処します。非表示の入力を送信すると、リクエストが送信されたときにページにチェックボックスが表示されていたことがわかります。

コントローラーのアクションメソッドのパラメーターにバインドするために、これを知っておく必要があるのは裏であると思います。次に、私が想定している3状態のブール値(nullable boolパラメータにバインドされている)を使用できます。私はそれを試していませんが、彼らがしたことを望んでいます。


4
ええ、これはページグリッドなどがあり、以前にいくつかのビジネスオブジェクトで選択されていたアイテムで選択を解除したい場合に便利です。
RichardOD 2009

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)

実際のビューでは、これをループする必要はなく、コードを1行変更するだけです。

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

詳細については、私のブログ投稿をご覧ください。


1
ありがとうございました!Everboydはまだ古いフォームの方法を使用しています。送信すると、このcollection []とrequest.form garbageなしでモデルにアクセスできます-これが私が探していたものです。+1+ビール
Piotr Kula 2013年

2
これが質問の一番の答えになるはずです。非常にシンプルで実装が簡単です。
Johan Gunawan 2014年

私がこの答えを見つける前に、これに対するエレガントな解決策を見つけるのにしばらく苦労しました。数年経ちますが、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で実行した方がよいことがわかりました。これはそのうちの1つで、もう1つ思い浮かぶのはラジオボタンです。

編集:これはプレビュー5にあり、明らかにバージョン間でYMMVです。


1
別の例を追加したいだけです:Object.Property =!String.IsNullOrEmpty(Request.Form ["NAME"]);
Gup3rSuR4c 2010

チェックされていない場合は例外になります
Xulfee

10

最初の値のみを読み取ることを選択しているように見えるため、チェックボックスがオンの場合は「true」、非表示の値のみが含まれる場合は「false」になります。これは、次のようなコードで簡単にフェッチできます。

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

8

@Dylan Beattie Great Find !!! どうもありがとうございました。さらに拡張するために、この手法はビューモデルアプローチでも完璧に機能します。MVCはとてもかっこいいです。Guidの配列を、ViewにバインドされたModelオブジェクトと同じ名前でプロパティにバインドするのに十分スマートです。例:

ViewModel:

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();
    }

ビューモデルの哲学に詳しい人なら誰でも喜ぶでしょう。これはチャンピオンのように機能します!


おかげで、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バージョンで機能しますが、問題はカルチャーが考慮されないことです(boolの場合は本当に重要であるかのように)。

少なくともMVC3では、ブール値を把握する「正しい」方法は、ValueProviderを使用することです。

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

権限を編集するときに、クライアントのサイトの1つでこれを行います。

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 2012年

理由はありません。他の方法よりもメリットがあるとは思いません。
Dan VanWinkle 2012年

1
申し訳ありませんが、実際には理由があります。私のコードを見ただけで、この1つのメソッドを5つの異なる呼び出しに使用していて、各メソッドからFormCollectionを渡す気がしませんでした。これは、何も渡さなくてもキーを取得する最も簡単な方法でした。
Dan VanWinkle 2012年

ええ、私はMVCが初めてです。そして、FormCollectionの代わりに型指定されたモデルを使用するのと同じように、Request.Paramsの代わりにFormCollectionを使用する方が一般的には良いということをどこかで読みました(したがって、実際にはモデルを使用し、Request.Paramsの使用を避けるのが最善です)。allPermissions変数やkeyAsIntなど、コードの他のものが使用されていないことに気付きました。回答ありがとうございます。
SwissCoder 2012年

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のコレクションプロパティと同じ名前のMVCデフォルトモデルバインディングチェックボックスリストを使用するだけです。それだ。

しかし、指摘しなければならない問題が1つあります。各チェックボックスコンポーネントには、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を削除すると、頭痛と歯ぎしりの後にこの問題が解決しました
Ody

この問題で使用しているMVCのバージョンは.net MVC 4.0です。
ChinaHelloWorld 2015年

2

これは、Html.CheckBox(...

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

4つのボックスをオン、オフ、オフ、オンにすると、true、false、false、false、true、falseがtrue、false、false、trueに変わります。私が必要なものだけ


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");
ジャマー2013

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.