web-dev-qa-db-ja.com

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

注意:この質問は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
}

そもそも気まぐれで、2番目に、ユーザーがチェックした項目については、FormCollectionはその値を単なるtrueではなく「true false」としてリストします。

明らかに、何かが足りない。これは、htmlフォーム内で機能するコレクション内のオブジェクトがUpdateModel()を使用して、またはModelBinderを介して更新されることを念頭に置いて構築されていると思います。

しかし、私のオブジェクトはこれに設定されていません。それはこれが唯一の方法であるという意味ですか?それをする別の方法はありますか?

247
Will

Html.CheckBoxは奇妙なことをしています - 結果のページでソースを表示すると、それぞれのチェックボックスの横に<input type="hidden" />が生成されているのがわかります。

これを試してみてください。私が試したばかりなので、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" />
<%}%>

チェックボックスはすべて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オブジェクトに解析します。かなりいいですね。

262
Dylan Beattie

HtmlHelperは、チェックされていない状態をコントローラに通知するための隠し入力を追加します。正しいチェックステータスを得るために:

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

あなたがなぜチェックボックスと同じ名前の隠しフィールドを入れたのか疑問に思う場合は、その理由は次のとおりです。

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

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

私は彼らがコントローラのアクションメソッドのパラメータにバインドするためにこれを知る必要があるという舞台裏を推測します。それから私が仮定するトライステートブール値を持つことができます(null許容のブールパラメータにバインドされています)。私はそれを試したことはありませんが、私はそれが彼らがしたことを望んでいます。

54
Simon_Weaver

また、<label for="checkbox1">Checkbox 1</label>を使用する必要があります。そうすれば、人々はラベルテキストとチェックボックス自体をクリックできるようになります。また、スタイルが簡単で、少なくともIEでは、ページのコントロールをタブ移動すると強調表示されます。

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

これは単に「ああ、それができる」ことだけではありません。その大幅なユーザーエクスペリエンスの向上。すべてのユーザーがラベルをクリックできるとわかっていなくても、多くのユーザーはそうするでしょう。

49
Simon_Weaver

私はこれらの答えのどれもがこれのために内蔵の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)

詳細は私の ブログ記事 をご覧ください。

27
Shawn Mclean

これが私がしてきたことです。

見る:


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

コントローラ:


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

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

私はHtml。*ヘルパーメソッドがそれほど有用でない場合があることに気付きました、そして私はそれを普通の古いHTMLの中でやるほうがましだ。これはそれらの1つであり、頭に浮かぶもう1つはラジオボタンです。

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

25
mmacaulay

それらは最初の値だけを読むことを選択しているように見えるので、これはチェックボックスがチェックされているときは "true"、隠されている値だけが含まれているときは "false"です。これは次のようなコードで簡単に取得できます。

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

@Dylan Beattieグレートファインド!!!ありがとうございます。さらに拡張するために、このテクニックはView Modelアプローチとも完璧に機能します。 MVCはとてもクールです。Guidsの配列を、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();
    }

View Modelの理念に精通している人なら誰でも喜ぶでしょう。これはChampのように機能します。

8
nautic20

また、各チェックボックスに別の名前を付けて、その名前を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) {
    ...
}

名前が同じであるため、ビューからの値はアクションに渡されます。

私はこの解決策があなたのプロジェクトにとって理想的ではないことを知っています、しかし私はその考えをそこに投げ出すであろうと思いました。

6
Darcy
<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";
         }
    }
5
bluwater2001

私はこの質問がMVC3が出ていなかったときに書かれたことを知っています、しかしこの質問に来てそしてMVC3を使っている人のために、あなたはこれをする「正しい」方法が欲しいかもしれません。

私は全体をやっていると思いますが

Contains("true");

物事は素晴らしく、きれいで、そしてすべてのMVCバージョンで動作します、問題はそれが文化を考慮に入れないということです(それが本当にboolの場合には問題になるように)。

少なくともMVC3では、boolの値を把握するための「正しい」方法は、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を知ることはないので、それらをその場で処理する必要があります。

4
Dan VanWinkle

この問題はリリース1.0でも発生しています。 Html.Checkbox()を使用すると、元のチェックボックスと同じ名前/ IDで別の隠しフィールドが追加されます。そして、私がdocument.GetElemtentsByName()を使ってチェックボックス配列をロードしようとしていたので、あなたは物事がどのように混乱しているかを推測することができます。それは奇妙です。

4
Farhan Zia

私が集めることができるものから、モデルはchecked = trueかfalseかを推測したくないので、このようなフォームを送信する前にjQueryを使ってcheckbox要素のvalue属性を設定することでこれを回避しました:

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

このように、チェックボックスの値を格納するためだけに隠し要素は必要ありません。

4
BraveNewMath

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>
<% } %>
3
ChinaHelloWorld

最も簡単な方法は...

名前と値を設定します。

<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
kk-dev11

これは私がHtml.CheckBoxを使用するときにdouble値を失うためにしたことです(...

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

4つのボックスをオン、オフ、オフにした場合は、true、false、false、false、true、falseがtrue、false、false、trueに変わります。必要なものだけ

2
Jeroen

私の解決策は:

<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-valid-boolean /

0
pawlom84

@ mmacaulayを使って、bool用にこれを思いつきました:

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

アクティブ= trueの場合

チェックしない場合はactive = false

0
Ravi Ram

チェックボックス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
eyesnz

私はほぼ同じ問題を抱えていましたが、私のコントローラーの戻り値は他の値でブロックされていました。

簡単な解決策を見つけましたが、それは少し荒いようです。

あなたのコントローラにViewbag.をタイプしてみてください、そして今あなたはそれにViewbag.Checkboolのような名前を付けます

それではビューに切り替えて、これで@Viewbag.Checkboolを試してみてください。これでControllerから値が得られます。

私のコントローラパラメータはこのように見えます:

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
treborian

このようなものはどうですか?

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

$(document).readyでこれをするだけです:

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

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

    }
});
0
doronAv