web-dev-qa-db-ja.com

MVC / Razorでは、複数のチェックボックスの値を取得し、それらをすべてコントローラーに渡すにはどうすればよいですか?

モデルのアイテムのリストを含むビューがあります。各行にチェックボックスを追加し、ユーザーに複数のチェックボックスを選択させ、選択された行の識別子をコントローラーに渡す必要があります。アクションリンクを介して単一の値を渡す方法は知っていますが、アクションリンクを介して複数の値を渡す方法や、選択された行を「収集」する方法はわかりません。コードの試行の一部を以下に示します。コントローラーに渡されたすべてのチェックボックスの値を取得できない理由を誰かが解決するのを手伝ってもらえますか?

これが私のページです

Checkbox     App ID     Date     Name
   []          1        5/10     Bob
   []          2        5/10     Ted
   []          3        5/11     Alice

ユーザーに必要なことは、行1と3(たとえば)を選択し、それらのアプリIDをコントローラーに渡すことです。

私はさまざまな試みをリストし始めましたが、私の現在の試みを見せて、誰かが私が間違っていることを指摘できるかどうかを見ることにしました。オンラインの例と私の例の主な違いは、私の例ではPagedListを使用し、foreachループでテーブルの行を作成することです。

パラメーターintsは、コントローラーにヒットするとブランクになります。チェックボックスから値を取得するにはどうすればよいですか?すべてのチェックボックスに同じ名前を付け、アクションリンクを介してICollectionを渡すという基本的なアイデアのために、このサイトを使用しました: http://haacked.com/archive/2008/10/23/model-binding-to- a-list.aspx /

見る:

@model PagedList.IPagedList<CarmelFinancialWeb.Models.ModelMerchantSummary>
<div class="block" style="width: 100%; float: left">
<p class="block-heading"> 
Merchant Application Report
</p>
<div class="table-holder">
    <table class="table" style="margin-bottom: 0px">
            <tbody>
                @foreach (var item in Model)
                {
                    <tr>
                        <td>
                            <input type="checkbox" name="ints" value=item.ApplicationID />
                        </td>
                    <td>
                        @Html.ActionLink(item.ApplicationID.ToString(), "ViewApplication", new { ID = item.ApplicationID, edit = 1 }, new AjaxOptions { HttpMethod = "GET" })
                    </td>
                    <td>
                        @Convert.ToDateTime(item.ApplicationDate).ToString("M/d/yy")
                    </td>
                    <td>
                        @item.ApplicantName
                    </td>
        </tbody>
    </table>
</div>
</div>
@Html.ActionLink("Print Application", "PrintApplication", "CreateContract", new { @class = "btn btn-primary" })

コントローラ:

    [AuthorizeAdmin]
    public ActionResult PrintApplication(ICollection<int> ints, string ID)
    {
        Contracts_Create contract = new Contracts_Create();
        ModelApplication currentApplication = new ModelApplication();
        currentApplication.contract = new ModelContract();
        return File(contract.CreatePDF_PrintedApplication_English(currentApplication.contract.location, currentApplication.contract), "application/pdf");
    }

編集:これは別の質問の複製としてタグ付けされました。そこには、連続していない入力名を使用できるかどうかについての質問がありました。私の問題は、非シーケンシャルではない入力を使用していることですが、まだ機能していません。私はその概念を理解していますが、特定のコードが機能していない理由がわかりません。私はこれに多くの時間を費やしましたが、特定のコードに対する答えが見つかりません。ありがとう!

10
boilers222

ViewModelをページに渡し、モデルバインダーを使用して同じビューモデルをコントローラーにポストバックしてみてください。

モデル:

public class MerchantModel
{
    public int AppId { get; set; }
    public string Name { get; set; }
    public bool IsSelected { get; set; }
}

public class MerchantViewModel
{
    public List<MerchantModel> Merchants { get; set; }
}

コントローラ:

public class DefaultController : Controller
{
    // GET: Default
    public ActionResult Index()
    {
        var merchant1 = new MerchantModel
        {
            AppId = 1,
            Name = "Bob"
        };
        var merchant2 = new MerchantModel
        {
            AppId = 2,
            Name = "Ted"
        };
        var merchant3 = new MerchantModel
        {
            AppId = 3,
            Name = "Alice"
        };

        List<MerchantModel> list = new List<MerchantModel>();
        list.Add(merchant1);
        list.Add(merchant2);
        list.Add(merchant3);

        var model = new MerchantViewModel
        {
            Merchants = list
        };

        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MerchantViewModel model)
    {
        return View(model);
    }
}

見る:

 @model TestCheckBoxes.Models.MerchantViewModel

    @{
        Layout = null;
    }

    <!DOCTYPE html>

    <html>
    <head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div> 
        <form action="/default/index" method="post">
            <table>
                @for (int i = 0; i < Model.Merchants.Count; i++)
                {
                    <tr>
                        <td>
                            @Html.CheckBoxFor(x => x.Merchants[i].IsSelected)
                        </td>
                        <td>
                            @Html.HiddenFor(x => x.Merchants[i].AppId)
                            @Model.Merchants[i].AppId
                        </td>
                        <td>
                            @Html.HiddenFor(x => x.Merchants[i].Name)
                            @Model.Merchants[i].Name
                        </td>
                    </tr>
                }
            </table>

            <button type="submit">Submit</button>
        </form>



    </div>
</body>
</html>

コントローラーの[HttpPost]メソッドに戻ると、bool値がtrueまたはfalseのMerchantModelのリストが表示されます。この方法で、それが本当かどうかを確認し、そこからAppIdを取得するだけです。

8
Nick Young

Mvcではforeachを使用せず、常にforとインデックス変数を使用して繰り返します。

また、選択状態を追跡するためにブール値が必要になります。

このサンプルコードは私のために機能します:

public class AModel
{
    public List<AnotherModel> Items { get; set; }
}

public class AnotherModel
{
    public int ApplicationId { get;set; }
    public DateTime ApplicationDate { get; set; }
    public string ApplicantName { get; set; }
    public bool Selected { get; set; }
}

Page.cshtml

@using (Html.BeginForm("PostIndex", "Home", FormMethod.Post))
{
    <table class="table" style="margin-bottom: 0px">
        <tbody>
        @for (var i = 0; i < Model.Items.Count(); i++)
        {
            <tr>
                <td>
                    <label>@Html.CheckBoxFor(model => model.Items[i].Selected) @Html.DisplayFor(model => model.Items[i].ApplicantName)</label>
                </td>
                <td>
                    @Html.ActionLink(Model.Items[i].ApplicationId.ToString(), "ViewApplication", new {ID = Model.Items[i].ApplicationId, edit = 1}, new AjaxOptions {HttpMethod = "GET"})
                </td>
                <td>
                    @Html.DisplayFor(model => model.Items[i].ApplicationDate)
                </td>
                <td>
                    @Html.DisplayFor(model => model.Items[i].ApplicationId)
                </td>
            </tr>
        }
        </tbody>
    </table>
    <input type="submit"/>
}
8
C Bauer

@CBauerと@NickYoungには本質的に答えがありました。キーは、(1)チェックボックスのIDが同じサフィックスの括弧内に連続番号で書き込まれていることを確認すること、(2)アクションリンクの代わりに送信ボタンを使用すること、(3)IDを受け入れるコントローラーを正しく記述することでした。チェックボックスから。私が仕事に着いたことのアイデアをあなたに与えるために私のコードのいくつかを投稿すると思いました:

ビュー(部分):

@model PagedList.IPagedList<CarmelFinancialWeb.Models.ModelMerchantSummary>

...

@{var i = 0;}
@foreach (var item in Model)
{
  var tmp = "[" + i + "].ints";
  <tr>
      <td>
          <input name="ints" type="checkbox" id="@tmp" class="chkclass" value="@item.ApplicationID" />
      </td>

...

<input id="Submit" type="submit" class="btn btn-primary" value="Print Application(s)" />

...

コントローラ:

[AuthorizeAdmin]
[HttpPost]
public ActionResult MerchantApplicationSummary(string[] ints, FormCollection form, int? page)
{

...

@CBauerと@NickYoungに感謝します!

0
boilers222