将IEnumerable <selectlistitem>传递给Controller

时间:2018-02-19 01:35:30

标签: c# .net asp.net-mvc razor

我正在HTTPGet中构建IEnumerable并将其传递给我的视图。我的问题是使用hiddenfor将所选信息返回给控制器。

    [HttpGet]
    public ActionResult Index(int id)
    {
        RANKDModel model = new RANKDModel();
        model.thingList = new List<thingsModel>();
        List<SelectListItem> thingRank = new List<SelectListItem>();

        var tblThingGroup = db.tblThingGroup.Where(x => x.thingCollectionID == id).Include(t => t.tblThing).Include(t => t.tblThingCollection).OrderBy(x => x.displayOrder);

        model.thingRank = new SelectList(thingRank, "Value", "Text");

        int i = 1;

        foreach (var thing in tblThingGroup)
        {
            thingRank.Add(new SelectListItem()
            {
                Value = thing.tblThing.thingID.ToString(),
                Text = i.ToString()
            });
            model.thingRank = new SelectList(thingRank, "Value", "Text");

            thingsModel things = new thingsModel();

            things.thingID = thing.tblThing.thingID;
            things.thingName = thing.tblThing.thingName;
            things.thingImgPointer = thing.tblThing.thingImgPointer;

            model.thingList.Add(things);
            i++;
        }

        return View(model);
    }

    [HttpPost]
    public ActionResult Index(RANKDModel model, IEnumerable<SelectListItem> thingRank)
    {
        //check model.Selecteditem
        return View(model);
    }

我的视图显示了下拉菜单,但我似乎无法将值传递回Post上的控制器。以下是我的观点。注释行是失败的尝试。我宁愿不在这里使用ajax。由于我的价值和我的文本字段都是我需要的,我觉得我应该能够将它们传递给控制器​​,即使它们不是模型的一部分(这很好但我在那里也没有成功) 。)

@using (Html.BeginForm())
{
    <div class="col-md-8">
        @Html.TextBoxFor(modelItem => Model.firstName, new { @class = "form-control" })
        @Html.TextBoxFor(modelItem => Model.lastName, new { @class = "form-control" })
    </div>

    <table class="table">
        @Html.HiddenFor(modelItem => Model.thingRank)

        @for (int i = 0; i < Model.thingList.Count; i++)
        {
            string imagePointer = "/Areas/RANKD/thingImages/" + Model.thingList[i].thingImgPointer;
            <tr>
                <td>
                    @Html.HiddenFor(modelItem => Model.thingList[i].thingID)

                    @Html.DropDownListFor(modelItem => modelItem.thingRank, (IEnumerable<SelectListItem>)ViewBag.thingRank, "Rank it Bro.") @*Model.thingRank.Items as IEnumerable<SelectListItem>)*@

                    @*@Html.HiddenFor(modelItem => modelItem.thingRank[Model.thingRank(i)].Value)*@

                    @Html.HiddenFor(modelItem => modelItem.thingRank[Model.thingRank.IndexOf(i)].Value)

                    @*@Html.HiddenFor(modelItem => modelItem.thingRank)*@

                    @Html.DisplayFor(modelItem => Model.thingList[i].thingName)
                </td>
                <td>
                    <img src="@imagePointer" alt="@Model.thingList[i].thingName" height="75" />
                </td>
            </tr>
        }

    </table>

    <input type="submit" value="RANK IT" class="btn btn-default" />
}

我在隐藏的内容中遗漏了什么?

在我的RANDModel中添加代码

[Serializable]
public class RANKDModel
{
    public string firstName { get; set; }
    public string lastName { get; set; }
    public List<thingsModel> thingList { get; set; }
    public IEnumerable<SelectListItem> thingRank { get; set; }
}

1 个答案:

答案 0 :(得分:1)

您在for循环中创建了许多下拉列表。我想你需要它们,所以用户可以在每一行中选择一些东西。现在你有这个:

@Html.DropDownListFor(modelItem => modelItem.thingRank, 
    (IEnumerable<SelectListItem>)ViewBag.thingRank, "Rank it Bro.")

因此,Razor视图引擎会创建许多HTML标记,并将name属性设置为thingRank。你不希望出现这种情况。您希望为每个元素赋予唯一的name。此外,当在每个下拉列表中选择某些内容时,您将在POST方法中的表单提交期间稍后使用它。因此,请在模型中添加一个属性:

public List<int> SelectedRanks { get; set; }

在GET操作中,您需要将该属性设置为与thingList相同的项目数,因为您需要为每个属性设置下拉列表。这样做:

// ...other code
model.SelectedRanks = new List<int>(model.thingList.Count);
return View(model);

现在在您的视图中,在for循环中使用此代码(请注意此处的索引操作):

@Html.DropDownListFor(modelItem => this.Model.SelectedRanks[i], 
    this.Model.thingRank, "Rank it Bro.")

现在每个下拉列表都会有一个唯一的name。例如,如果您有3个下拉列表,则其名称为:SelectedRanks[0]SelectedRanks[1]SelectedRanks[2]

当用户提交表单时,您可以从每个下拉列表中检索选定的值,如下所示:

[HttpPost]
public ActionResult Index(RANKDModel model)
{
    // model.SelectedRanks will have the value selected
    // For example, model.SelectedRanks[0] will have the value selected
    // in the first dropdown, model.SelectedRanks[1] will have value 
    // selected in the second dropdown and so on.
}

一些最终建议

  1. 请为您的酒店提供有意义的名称。例如,thingList不是一个有意义的名称。
  2. 对类名和属性名使用Pascal表示法。因此,thingList应该是ThingList而不是RANKDModel
  3. 如果您的首字母缩写为2个字符,请使用大写字母,否则请使用Pascal表示法。例如,RankdModel应为RankedModel(不应该拼写WITH CountData AS ( SELECT A , B , C , rate FROM dataframe WHERE A + B + C = 2 ) ,ProbData AS ( SELECT A , B , C , rate FROM dataframe WHERE A + B + C = 1 ) SELECT a.A,a.b,a.c,MAX(a.rate) AS probabilities, MAX(CASE WHEN a.A = 1 AND b.A = 1 and b.B = 0 and b.C = 0 THEN b.rate ELSE 0 END) AS individual_prob_A, MAX(CASE WHEN a.B = 1 AND b.A = 0 and b.B = 1 and b.C = 0 THEN b.rate ELSE 0 END) AS individual_prob_B, MAX(CASE WHEN a.C = 1 AND b.A = 0 and b.B = 0 and b.C = 1 THEN b.rate ELSE 0 END) AS individual_prob_C FROM CountData AS a , ProbData AS b GROUP BY a.A,a.b,a.c ?)