1

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

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

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

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

具有键“BrandName”的 ViewData 项属于“System.String”类型,但必须属于“IEnumerable”类型。

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

医疗产品

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; }
}

医疗产品视图模型

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; }
}

医疗产品控制器

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);            
    }
}

医疗产品映射器

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;
    }
}

编辑.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")
}
4

1 回答 1

0

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

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

anything => anything.BrandName

与使用model代替anything

这种情况下的 lambda 表达式你可以把它想象成一个看起来像这样的方法

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

至于下拉菜单,这里有一篇很好的文章,解释了如何创建下拉菜单

如何编写一个简单的 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);

所以看到这行得通,我唯一能猜到的是你的问题出在你的映射器上,你能举一个viewModel.BrandSelectListItem从数据库中获取数据后等于的例子吗?输入虚假数据对你有用吗?

编辑2:

SelectListItem如果您要将queryBrands转换为IEnumerable<SelectListItem>

您可以修改现有的

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
                                 });
于 2013-09-25T22:33:17.877 回答