【问题标题】:how to store Multiple selction / Dropdownlist in C#如何在 C# 中存储多选/下拉列表
【发布时间】:2017-01-10 22:34:59
【问题描述】:

我是 MVC 和 C# 的新手,对于一个项目,我试图让用户从列表中多选城市并稍后将其存储到数据库中。我已经阅读了几篇关于此的帖子,但无法弄清楚如何解决我的问题。我可以存储表单的所有其他项目:

@using ( Html.BeginForm( "AddProjectInfo", "Insert", FormMethod.Post, new {
        enctype = "multipart/form-data"
        @id = "insertform", @class = "form-horizontal col-md-4 col-md-offset-4"
    } ) )

但对于城市,它只存储第一个选定的项目而不是全部。你能帮我解决这个问题吗?

这是我的看法:

<div class="form-group">
        <label class="col-sm-3 col-form-label text-left">City * </label>
        <div class="col-sm-9">
            @Html.DropDownList(
             "City",
             new SelectListItem[] {
                    new SelectListItem {
                        Text = "Cambridge", Value = "Ca"
                    },
                   new SelectListItem {
                        Text = "Oxford", Value = "Ox"
                    },
                    new SelectListItem {
                        Text = "Sheffield", Value = "Sh"
                    }                
             },
         "--Select Cities--",
    new {
        @class = "form-control",
        required = true,
        multiple = "multiple"
    }
        )
    </div>
</div>

这是我的控制器:

[HttpPost]
    public ActionResult Insert( FormCollection frm ) {
        Models.ProjectInfo p = new Models.ProjectInfo();
        String[] Cities= frm.GetValues( "City" );
        p.ContractId = frm[ "ContractId" ];
        p.Year = Convert.ToDecimal( frm[ "Year" ] );
        p.City = Cities.ToString();
        p.Location = frm[ "Location" ];
        // Insert into the Database
            AddProjectInfo( p );
            ViewBag.ResponseMessage = "Submitted !";

    }

我知道如何使用 JavaScript 做到这一点,但不知道 C# 如何处理它。 谢谢你!

【问题讨论】:

  • public ActionResult Insert(FormCollection frm) 这应该是一个真实的模型,其字段对应于html中的输入
  • 不要使用DropDownList()multiple - 使用ListBoxFor()(参考this answer)。并且永远不要使用FormCollection。创建视图模型并绑定到属性 - 参考 this answer 了解典型实现

标签: c# asp.net-mvc formcollection


【解决方案1】:

我会提前告诉您,我编写了这些示例并没有对其进行测试,但这只是为了让您大致了解如何正确处理下拉列表/列表框。另外,最后,我会留下指向我的 GitHub 的链接,在那里我有一个简单的项目,这是我前段时间专门针对此类情况编写的。

那么,让我们开始吧。为了简单起见,我宁愿在 Controller 中创建下拉列表。例如:

假设您有一个模型:

public class Person
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public string City { get; set; }

    [NotMapped]
    public SelectList CitySelectList { get; set; }
}

注意CitySelectList,它是NotMapped,因为我们不希望它连接到数据库。 CitySelectList的值会通过City保存在DB中

然后你有一个动作方法:

public ActionResult Insert()
{
    var person = new Person { CitySelectList = new SelectList(
    new List<SelectListItem>
        {
            new SelectListItem { Text = "Cambridge", Value = "Ca" },
            new SelectListItem { Text = "Oxford", Value = "Ox" },
            new SelectListItem { Text = "Sheffield", Value = "Sh" }
        }, "Value", "Text") };

    return View(person);
}

在这里你可以看到我正在创建一个Person 的实例并将它传递给视图。这是加载具有预定义值的视图的最佳方式。在这种情况下,最重要的预定义值是下拉列表。

视图看起来或多或少像这样:

@model Person

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-group">
        @Html.LabelFor(m => m.Name, htmlAttributes: new { @class = "control-label" })
        @Html.EditorFor(m => m.Name, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(m => m.Name, "", new { @class = "text-danger" })
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Surname, htmlAttributes: new { @class = "control-label" })
        @Html.EditorFor(m => m.Surname, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(m => m.Surname, "", new { @class = "text-danger" })
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.City, htmlAttributes: new { @class = "control-label" })
@* Important *@
        @Html.EditorFor(m => m.CitySelectList, new { htmlAttributes = new { @class = "form-control", multiple = "multiple" } })
@* /Important *@
        @Html.ValidationMessageFor(m => m.City, "", new { @class = "text-danger" })
    </div>

}

如您所见,我通过 EditorFor 调用下拉列表,传递 2 个 htmlAttributes。最重要的是multiple = "multiple",因为它将定义我将在页面中显示的项目列表的类型。如何?通过专门为处理它而构建的编辑器模板。如果你不熟悉它的概念和用法,你可以查看this website 开始。编辑器模板如下:

@model SelectList

@{
    var htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(ViewData["htmlAttributes"]);
}

@if (!htmlAttributes.ContainsKey("multiple"))
{
    @Html.DropDownListFor(m => m.SelectedValue, Model.SelectListItems, htmlAttributes)
}
else
{
    @Html.ListBoxFor(m => m.SelectedValues, Model.SelectListItems, htmlAttributes)
}

有关此特定编辑器模板的一个细节:您是否注意到我正在为 SelectedValue(s) 创建下拉列表/列表框?当您获取所有值时,这可能会引起一些头痛,但您可以在 POST 方法中以这种方式处理:

[HttpPost]
public ActionResult Insert(Person person)
{
    person.City = person.CitySelectList.SelectedValues;
    // Some code goes here
    return View();
}

应该是这样的。但是,正如我之前所说,我有一个工作代码here,所以你可以运行并查看它是如何工作的。如果您需要,还可以从 GitHub right here 对该代码进行一些解释。

【讨论】:

  • 使用new SelectList(..) 从第一个IEnumerable&lt;SelectListItem&gt; 创建第二个相同的new SelectList(..) 是没有意义的。这不会提供客户端或服务器端验证,在编辑现有数据时不能用于正确的 2 路模型绑定,不会设置 City 的值(SelectedValuesIEnumerable),当 @987654340 时将丢失所有选项@被称为等等等等。
  • 是的,但正如我在第一行所说的那样,“(...)我编写了这些示例而没有对其进行测试,但这只是为了给您一个大致的想法(...)”。
  • 一般的想法是强绑定到模型属性(在 OP 情况下会说IEnumerable&lt;string&gt; SelectedCities,而不是SelectListSelectedValues 属性:)
【解决方案2】:
 @Html.ListBoxFor(m => m.location_code, Model.location_type)        
    [HttpPost]
        public string SaveResults(List<int> location_code)
        {

            if (location_code!= null)
            {
                return string.Join(",", location_code);
            }
            else
            {
                return "No values are selected";
            }
        }

【讨论】:

    猜你喜欢
    • 2016-05-21
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多