简体   繁体   English

如何在ASP.NET MVC应用程序中使用多重选择?

[英]How to use multi selection in ASP.NET MVC application?

Two days already I am trying to figure out and learn how to build multi-selection dropdown list in ASP.NET Core, that is seeded from db context, and results are used further in the constructor, so I decided to ask this question. 已经两天了,我试图找出并学习如何在ASP.NET Core中构建多选下拉列表,该列表是从db上下文中获得的,结果在构造函数中得到了进一步使用,因此我决定提出此问题。 I did not find anywhere how to use data from posted form, so maybe you will be able to help me. 我在任何地方都找不到如何使用已发布表格中的数据的方法,因此也许您可以为我提供帮助。 I belive that I did some mistakes in my POST action in controller. 我相信我在控制器的POST操作中犯了一些错误。 I am not sure how I am supposed to get posted data into the controller. 我不确定如何将发布的数据发送到控制器中。

I was trying various combinations on simple example. 我在一个简单的例子上尝试各种组合。 Best what I have now is: 现在最好的是:

ViewModel.cs: ViewModel.cs:

public class ProductViewModel
    {
        public List<SelectListItem> Products { get; set; }
        public int[] ProductIDs { get; set; }
    }

Index.cshtml: Index.cshtml:

<!DOCTYPE html>
<html>
<head>
    <title>Aplikacja</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="~/dist/allstyles.css" />
</head>
<body>
    <form asp-action="Index" method="post">
        <input type="hidden" asp-for="Products" />

        <div class="form-group">
            <label asp-for="Products">Produkty</label>
            <select asp-for="ProductIDs" class="form-control" asp-items="ViewBag.Lista"></select>
        </div>
        <div class="text-center">
            <button class="btn btn-primary" type="submit">Save</button>
            <a asp-action="Index" class="btn btn-secondary">Cancel</a>
        </div>
    </form>

//ViewBag tests from controller
    @ViewBag.Message  //test1, returns 0
    @ViewBag.Message2 //test2, returns 0

</body>
</html>

Controller.cs Controller.cs

public class ProductController : Controller
{
    private readonly ApplicationDbContext _context; //database context

    public ProductController(ApplicationDbContext context)
    {
        _context = context; //context for controller
    }
    //GET
    public ActionResult Index()
    {
        ProductViewModel productVM = new ProductViewModel(); //viewmodel instance
        PopulateProducts(); //populating dropdown
        return View(productVM); //returning viewmodel
    }
    //POST (I belive that here I have screwed something a lot, I do not understand everything what is going on in this action)
    [HttpPost]
    public ActionResult Index(ProductViewModel productVM)
    {
        PopulateProducts(); 

        if (productVM.ProductIDs !=null)
        {
            List<SelectListItem> selectedItems = productVM.Products.Where(p => productVM.ProductIDs.Contains(int.Parse(p.Value))).ToList();

            ViewBag.Message = selectedItems.Count.ToString(); //returns 0
            ViewBag.Message2 = productVM.Products.Count.ToString();//returns 0
        }
        return View(productVM);
    }

    private void PopulateProducts() //method populating dropdown list
    {

        var techQuery = from t in _context.Products //getting products context from database
                        orderby t.Name //sorting by names
                        select t; //selecting item (??)

        if (techQuery != null) //if db context var is not null...
        {
            ViewBag.Lista = techQuery.Select(n => new SelectListItem { Text = n.Name, Value = n.ProductID.ToString() }); //...creating viewbag that is used for populating dropdown list in view

        }
    }
}

For selectedItems , I think you need to retrive from ViewBag.Lista instead of productVM.Products . 对于selectedItems ,我认为您需要从ViewBag.Lista而不是productVM.Products检索。 When Posting Form from View to Controller , ProductViewModel.Products will always be null. ViewController发布FormProductViewModel.Products始终为null。

I suggest you try workaround below by using ViewBag.Lista . 我建议您使用ViewBag.Lista在下面尝试解决方法。

    public ActionResult ProductSelect(ProductViewModel productVM)
    {
        PopulateProducts();

        if (productVM.ProductIDs != null)
        {
            List<SelectListItem> selectedItems = ((IEnumerable<SelectListItem>)ViewBag.Lista)
                .Where(p => productVM.ProductIDs.Contains(int.Parse(p.Value))).ToList();

            ViewBag.Message = selectedItems.Count.ToString(); //returns 0
            ViewBag.Message2 = ((IEnumerable<SelectListItem>)ViewBag.Lista).Count().ToString();//returns 0
        }
        return View(productVM);
    }

The solution is pretty simple & You're almost there. 解决方案非常简单,而且您快到了。 I am going to suggest few of the changes. 我将建议一些更改。 In ViewModel.cs, it is good idea to populate the list property thru a constructor. 在ViewModel.cs中,最好通过构造函数填充list属性。 It avoids Null Reference exceptions & makes it easy to use the object. 它避免了Null引用异常,并易于使用该对象。

 public ProductViewModel()
    {
        Products=new List<SelectListItem>();
    }
    public List<SelectListItem> Products { get; set; }
    public int[] ProductIDs { get; set; }

In controller.cs, I would make changes to return PopulateProducts to return List Of SelectList, rather than populating view bag. 在controller.cs中,我将进行更改以返回PopulateProducts以返回SelectList列表,而不是填充视图包。 Note: Please close the DB Connection as you will run out connection pools eventually. 注意:请关闭数据库连接,因为最终将耗尽连接池。

public class ProductController : Controller
{
    private readonly ApplicationDbContext _context; //database context

    public ProductController(ApplicationDbContext context)
    {
        _context = context; //context for controller
    }
    //GET
    public ActionResult Index()
    {
        ProductViewModel productVM = new ProductViewModel(); //viewmodel instance
        productVM.Products=PopulateProducts(); //populating dropdown

        return View(productVM); //returning viewmodel
    }
    //POST (I belive that here I have screwed something a lot, I do not understand everything what is going on in this action)
    [HttpPost]
    public ActionResult Index(ProductViewModel productVM)
    {
        productVM.Products= PopulateProducts();

        if (productVM.ProductIDs != null)
        {
            List<SelectListItem> selectedItems = productVM.Products.Where(p => productVM.ProductIDs.Contains(int.Parse(p.Value))).ToList();

            ViewBag.Message = selectedItems.Count.ToString(); //returns 0
            ViewBag.Message2 = productVM.Products.Count.ToString();//returns 0
        }
        return View(productVM);
    }

    private List<SelectListItem> PopulateProducts() //method populating dropdown list
    {

        var techQuery = from t in _context.Products //getting products context from database
            orderby t.Name //sorting by names
            select t; //selecting item (??)

        if (techQuery != null) //if db context var is not null...
        {
            return techQuery.Select(n => new SelectListItem { Text = n.Name, Value = n.ProductID.ToString() }).ToList(); //...creating viewbag that is used for populating dropdown list in view

        }

        return null;
    }
}

Finally, in index.cshtml, you need to specify the model that is expected for the view & populate product ids from @Model.Products. 最后,在index.cshtml中,您需要指定用于查看的模型,并在@ Model.Products中填充产品ID。

@model ProductViewModel
<form asp-action="Index">
<div class="form-group">
    <label asp-for="Products">Products</label>
    <select asp-for="ProductIDs" class="form-control" asp-items="@Model.Products"></select>
</div>
<div class="text-center">
    <button class="btn btn-primary" type="submit">Save</button>
    <a asp-action="Index" class="btn btn-secondary">Cancel</a>
</div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM