如何在下拉列表中放置数据库中的BrandNames列表

时间:2013-09-25 21:52:31

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

我正在尝试使用Html.DropDownListFor()在我的edit.cshtml文件的下拉列表中列出医疗产品品牌名称。我正在尝试正确使用Html助手,但我的努力没有成功。 Model.BrandSelectListItem是一个IEnumerable,应该进入DropDownList。

另外,我不明白为什么我需要在lambda表达式中将模型引用为“model”,而在以下代码段的第二个参数中引用为“Model”:

@Html.DropDownListFor(model => model.BrandName, Model.BrandSelectListItem)

执行代码时,收到以下运行时错误:

  

具有键'BrandName'的ViewData项是类型   'System.String'但必须是'IEnumerable'类型。

以下是可能与此错误相关的一些类:

MedicalProduct

public class MedicalProduct
{
    [Key]
    public int ID { get; set; }

    [Required]
    [StringLength(50)]
    public string Name { get; set; }

    [Required]
    [DataType(DataType.Currency)]
    public double Price { get; set; }

    // is a foreign key
    public Nullable<int> BrandID { get; set; }
}

MedicalProductViewModel

public class MedicalProductViewModel
{
    [Key]
    public int ID { get; set; }

    [Required]
    [StringLength(50)]
    public string Name { get; set; }

    [Required]
    [DataType(DataType.Currency)]
    public double Price { get; set; }

    public Nullable<int> BrandID { get; set; }

    [DisplayFormat(NullDisplayText="[Generic]")]
    public string BrandName { get; set; }

    public IEnumerable<SelectListItem> BrandSelectListItem { get; set; }
}

MedicalProductController

public class MedicalProductController : Controller
{
    private MvcMedicalStoreDb _db = new MvcMedicalStoreDb();

    //
    // GET: /MedicalSupply/Edit/5

    public ActionResult Edit(int id = 0)
    {
        MedicalProduct medicalProduct = _db.Products.Find(id);
        if (medicalProduct == null)
        {
            return HttpNotFound();
        }

        var viewModel = GetMedicalProductViewModel(medicalProduct);
        return View(viewModel);
    }

    public MedicalProductViewModel GetMedicalProductViewModel(MedicalProduct product)
    {
        var mapper = new MedicalProductMapper(_db);

        return mapper.GetMedicalProductViewModel(product);            
    }
}

MedicalProductMapper

public class MedicalProductMapper
{
    private MvcMedicalStoreDb _db;

    public MedicalProductMapper(MvcMedicalStoreDb db)
    {
        _db = db;
    }

    public MedicalProductViewModel GetMedicalProductViewModel(MedicalProduct source)
    {
        MedicalProductViewModel viewModel = new MedicalProductViewModel();
        var dbBrands = _db.Brands.ToArray();

        viewModel.ID = source.ID; 
        viewModel.Name = source.Name;
        viewModel.Price = source.Price;
        viewModel.BrandID = source.BrandID;
        if (viewModel.BrandID != null)
            viewModel.BrandName = dbBrands.SingleOrDefault(b => b.ID == source.BrandID).Name;

        var queryBrands = from b in dbBrands
                          select b;

        // BrandSelectListItem is 'null' before this assignment statement executes. 
        // and Stays null after the statement executes, why?
        viewModel.BrandSelectListItem = queryBrands as IEnumerable<SelectListItem>;

        return viewModel;
    }
}

Edit.cshtml

@model MvcMedicalStore.Models.MedicalProductViewModel

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

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

    <fieldset>
        <legend>MedicalProduct</legend>

        @Html.HiddenFor(model => model.ID)

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Price)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Price)
            @Html.ValidationMessageFor(model => model.Price)
        </div>


        <div class="editor-label">
            @Html.LabelFor(model => model.BrandName)
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(model => model.BrandName, Model.BrandSelectListItem)
            @Html.ValidationMessageFor(model => model.BrandName)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

1 个答案:

答案 0 :(得分:0)

  

另外,我不明白为什么我需要将模型称为'模型'   在lambda表达式中,但作为'Model'的第二个参数   以下代码段:

您无需在lambda表达式中将其作为模型引用。 lambda的第一部分(在=&gt;符号之前)你只是指定你的参数,你可以随意命名它们

anything => anything.BrandName

与使用model取代anything

相同

在这种情况下,lambda表达式可以将其视为一个看起来像这样的方法

TProperty GetPropertyYouWantToCreateADropdownFor(MedicalPropertyViewModel model)
{
    return model.BrandName
}

至于下拉列表,这里有一篇很好的帖子,解释了如何创建下拉列表

How to write a simple Html.DropDownListFor()?

修改

我插入了除映射器之外的所有代码,并且只是对ViewModel进行了一些虚假的实现。你的代码工作正常。

这是我用于假控制器的内容

 var viewModel = new MedicalProductViewModel
 {
     BrandID = 12,
     BrandName = "Some Brand",
     ID = 6,
     Name = "Some Name",
     Price = 12.27,
     BrandSelectListItem = new List<SelectListItem>()
     {
           new SelectListItem() {Text = "Item 1", Value = "1"},
           new SelectListItem() {Text = "Item 2", Value = "2"}
     }
 };

 return View(viewModel);

所以看到这个有效,我唯一可以猜到的是你的问题出在你的Mapper中,你能举例说明从数据库中获取数据后viewModel.BrandSelectListItem等于什么?扔假数据对你有用吗?

编辑2:

如果您要将SelectListItem

转换为IEnumerable<SelectListItem>,则

queryBrands必须与var queryBrands = from b in dbBrands select b; 兼容

您可以修改现有的

var queryBrands = dbBrands.Select(b => new SelectListItem() 
                                 {
                                     Text = b.PropertyWithWhatYouWantToDisplay,
                                     Value = b.PropertyYouWantAsTheValue,
                                     Selected = //true if you want this item selected, false otherwise
                                 });

类似

{{1}}