在MVC 5中填充DropDownList

8
这是我关于 AddNewProductViewModel 的代码。
using AccessorizeForLess.Data;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web;

namespace AccessorizeForLess.ViewModels
{
    public class AddNewProductViewModel
    {
        public string Name { get; set; }

        [DataType(DataType.MultilineText)]
        public string Description { get; set; }

        public decimal Price { get; set; }

        public string AltText { get; set; }

        public int Quantity { get; set; }

        public string ImagePath { get; set; }

        public HttpPostedFileBase Image { get; set; }

        public List<ProductCategory> Category { get; set; }
    }
}

这是我的控制器中创建(Create)方法的代码:

[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Create(AddNewProductViewModel model)
        {
            ProductImageViewModel image = new ProductImageViewModel() { ImagePath = "/Content/ProductImages/" + model.Image.FileName, AltText = model.AltText };
            ProductImage newImage = new ProductImage() { ImagePath = image.ImagePath, AltText = image.AltText };
            entities.ProductImages.Add(newImage);
            await entities.SaveChangesAsync();
            int ImageId = newImage.ProductImageId;

            Product product = new Product()
            {
                ProductImageId = ImageId,
                ProductName = model.Name,
                ProductDescription = model.Description,
                ProductPrice = model.Price,
                Quantity = model.Quantity
                CategoryID = model.
            };

            string file = model.Image.FileName;
            string path = Server.MapPath(@"~/Content/ProductImages");
            string fullPath = path + @"\" + file;
            try
            {
                model.Image.SaveAs(path + @"\" + file);

                if (ModelState.IsValid)
                {
                    entities.Products.Add(product);
                    await entities.SaveChangesAsync();
                    return RedirectToAction("Create");
                }
            }
            catch (Exception ex)
            {
                ViewBag.Message = ex.ToString();
            }
           //ViewBag.ProductImageId = new SelectList(entities.ProductImages, "ProductImageId", "ImagePath", product.ProductImageId);
            return View("Create");
        }

现在我正在尝试在视图中填充下拉列表:

<div class="form-group">
            @Html.LabelFor(model => model.Category, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.Category.Id, new SelectList(Model.Category,"Value","Text"), "- Please Select -")
                @Html.ValidationMessageFor(model => model.Category)
            </div>
        </div>

以下是我收到的错误信息:

CS0411: 方法'System.Web.Mvc.Html.SelectExtensions.DropDownListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression<, System.Collections.Generic.IEnumerable<SelectListItem>>, object)'的类型参数无法从使用中推断。请尝试明确指定类型参数。

编辑

这是新的AddNewProductViewModel

using AccessorizeForLess.Data;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web;

namespace AccessorizeForLess.ViewModels
{
    public class AddNewProductViewModel
    {
        public string Name { get; set; }

        [DataType(DataType.MultilineText)]
        public string Description { get; set; }

        public decimal Price { get; set; }

        public string AltText { get; set; }

        public int Quantity { get; set; }

        public string ImagePath { get; set; }

        public HttpPostedFileBase Image { get; set; }

        public ProductCategory Category { get; set; }

        public int SelectedCategoryId { get; set; }

        public List<ProductCategory> Categories { get; set; }
}
}

这是我的更新版本下拉列表

<div class="form-group">
            @Html.LabelFor(model => model.Category, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.SelectedCategoryId,
                 new SelectList(Model.Categories, "CategoryId", "CategoryName"), "- Please Select -")
                @Html.ValidationMessageFor(model => model.Category)
            </div>
        </div>

现在我在这一行代码上遇到了NullReferenceException异常。
@Html.DropDownListFor(model => model.SelectedCategoryId,

鉴于我的代码,有人能否请指出我在这里做错了什么,我从昨晚开始就一直在苦苦挣扎。


您没有名为 Category 的属性,该属性是一个复杂对象,其中包含属性 ID(属性 Category 是一个 List<ProductCategory>)。 - user3559349
你需要一个额外的属性(比如)int CategoryID 来绑定下拉列表,并建议你将集合命名为(比如)CategoryList,以便清楚地了解你的属性。 - user3559349
@StephenMuecke 我更新了我的代码,但是我改得越多就越困惑。根据我的代码(如果需要更多代码请告诉我),你能否向我展示如何完成这个任务。到目前为止我已经尝试了所有的方法。 - PsychoCoder
1
最好的猜测是,当您首次呈现视图时它可以工作(假设“Categories”已正确填充),并且当您发布并返回视图时会出现异常。您使用的return View(“Create”);不会返回模型,因此new SelectList(Model.Categories ...会抛出异常,因为Model.Categories为空。您需要重新填充集合并使用return View(model); - user3559349
3个回答

9
我解决了这个问题(感谢大家提供的技巧)。以下是针对像我一样遇到类似问题的人。
我将我的创建(Create)方法更改为如下格式:
// GET: /Products/Create
public ActionResult Create()
{
    var p = new AddNewProductViewModel();
    p.Categories = entities.ProductCategories.ToList();
    return View(p);
}

我的 AddNewProductViewModel 如下所示:

using AccessorizeForLess.Data;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web;

namespace AccessorizeForLess.ViewModels
{
    public class AddNewProductViewModel
    {
        public string Name { get; set; }

        [DataType(DataType.MultilineText)]
        public string Description { get; set; }

        public decimal Price { get; set; }

        public string AltText { get; set; }

        public int Quantity { get; set; }

        public HttpPostedFileBase Image { get; set; }

        public int SelectedCategoryId {get;set;}
        public List<ProductCategory> Categories { get; set; }
        public ProductCategory Category { get; set; }
    }
}

在我看来:
<div class="form-group">
    @Html.LabelFor(model => model.SelectedCategoryId, "Category",new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.DropDownListFor(model => model.SelectedCategoryId, new SelectList(Model.Categories, "CategoryId", "CategoryName"), "- Please Select -")
        @Html.ValidationMessageFor(model => model.SelectedCategoryId)
    </div>
</div>

感谢大家的帮助 :)

3

首先我会更改您的ViewModel,包括一个SelectedCategoryId,并将选项更改为Categories

在没有看到您的get代码之前,我假设ProductCategory类似于以下内容:

public class ProductCategory {
  public int Id {get;set;}
  public string Name { get;set;}
}

你的剃须刀标记将变成以下内容:
<div class="form-group">
     @Html.LabelFor(model => model.Categories, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(model => model.SelectedCategoryId, 
            new SelectList(Model.Categories, "Id", "Name"), "- Please Select -")
            @Html.ValidationMessageFor(model => model.Categories)
        </div>
</div>

第一个参数是所选类别,您的选项来自于 Categories

WorkingFiddle


1
使用控制器构建列表,然后从视图中调用该列表。
控制器:
public static List<SelectListItem> GetDropDown()
    {
        List<SelectListItem> ls = new List<SelectListItem>();
        lm = (call database);
        foreach (var temp in lm)
        {
            ls.Add(new SelectListItem() { Text = temp.name, Value = temp.id });
        }
        return ls;
    }

呼叫下拉菜单:
@Html.DropDownListFor(x => x.Field, PathToController.GetDropDown())

我建议使用非静态的帮助方法,并在您的操作方法中使用它来填充ViewModel。尽量限制从Razor模板调用的次数,除了从ViewModel读取数据。 - Carl in 't Veld

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接