0

我有一个对模型 RawValues 进行强类型化的视图。在这个视图中,我想要一个 DropDownList 包含一个胶囊列表(它们在不同的模型中定义,胶囊模型)。我想将选定的 Capsule 绑定到我的 RawValues 模型中的 CapsuleFk 属性。

我试图弄清楚当我搭建 RawValues 模型时,如何让包含不同 Capsules 的 DropDownList (@Html.DropDownListFor) 自动生成到我的视图中。我的 DropDownList 中的项目将来自 Capsule 表,其中包含 4 条记录。下面,您将看到我如何ForeignKey为我的属性设置public int? CapsuleFk属性。这是我在视图中显示的模型,在这个模型下方,您将看到 Capsule 模型:

namespace CapWorx.QuikCap.Models
{
    public class RawValues
    {
        [Key]
        public int Pk { get; set; }

        public int? FillerFk { get; set; }
        [ForeignKey("FillerFk")]
        public virtual Filler Filler { get; set; }

        public int? CapsuleFk { get; set; }
        [ForeignKey("CapsuleFk")]
        public virtual Capsule Capsule { get; set; }

        public int Active1 { get; set; }
        public int Active2 { get; set; }
        public int Active3 { get; set; }
        public int Active4 { get; set; }
        public int Active5 { get; set; }
        public int KeyActive { get; set; }
        public int KeyActivePackStat { get; set; }
        public bool E4M { get; set; }
        public bool K100M { get; set; }
        public string CreatedBy { get; set; }
        public DateTime CreatedDate { get; set; }
    }
}

这是胶囊模型:

namespace CapWorx.QuikCap.Models
{
    public class Capsule
    {
        [Key]
        public int Pk { get; set; }
        public string Name { get; set; }
    }
}

我希望有一些明显的事情我做的不对。当我运行我的应用程序时,它会自动在我的本地环境中创建我的 SQL 数据库(如预期的那样)。这是直接来自 SQL Server Management Studio 的我的外键关系的屏幕截图,这似乎是正确的。注意我的外键基表是正确的(RawValues),我的主键基表也是正确的(Capsule):

在此处输入图像描述

你能帮我确定我做错了什么,以便我可以在我的 RawValues 视图上创建一个 DropDownList ,其中包含一个胶囊列表,然后我可以将选定的胶囊绑定到我的 RawValues 模型中的 CapsuleFk 属性?

谢谢!

4

1 回答 1

1

当您尝试将业务或数据对象直接绑定到视图时,您会遇到常见问题。这是一个 MUUUUCH 更清洁的解决方案,用于创建您的 View 绑定到的“ViewModel”,并且此 ViewModel 将包含 View 为其 UI 所需的所有内容。

这是我使用的模式。首先,ViewModel:

public class RawValuesEditingViewModel
{
    // Your primary ID
    public int Pk { get; set; }

    [Required]
    public int? SelectedCapsulePk { get; set; }

    // Other basic fields as needed for editing on this screen
    public int Active1 { get; set; }
    public int Active2 { get; set; }
    public int Active3 { get; set; }
    public int Active4 { get; set; }
    public int Active5 { get; set; }
    public int KeyActive { get; set; }
    // blah blah blah....

    // Use this as the source for your Dropdown List for the capsule choice
    public IEnumerable<SelectListItem> CapsulesToSelectFrom
    {
        get
        {
            return from cap in DatabaseRepository.GetAllCapsules() // or some kind of Repo here.
                   select new SelectListItem {
                       Text = cap.Name,
                       Value = cap.Pk.ToString(),
                       Selected = (cap.Pk == this.SelectedCapsulePk), 
                   };
        }
    }

    public RawValuesEditingViewModel()
    {
        // This constructor is parameter-less because the MVC model binder needs it this way to bind on post back.
        // You can alter this behavior, but it gets hairy.
    }

    // Call this method from your Controller to populate the ViewModel fields. 
    public void LoadModelFieldsFromDataObject(int pkToLoadFrom)
    {
        // get the underlying database object, from EF in your case.
        var rawValuesObj = DatabaseRepository.GetRawValueObjectById(pkToLoadFrom);

        // Map your RawValues data object fields to the RawValuesEditingViewModel fields as needed.
        // Only map the fields you want to present for editing.
        // Check out "AutoMapper" if you are tired of writing this kind of code :)
        this.Pk = rawValuesObj.Pk;
        this.SelectedCapsulePk = rawValuesObj.CapsuleFk; 
        // etc etc etc
    }

    public void ExecuteRawValuesUpdate(int pk)
    {
        // code to persist back to database goes here.
        // probably you will re-fetch the database object, update its fields from this ViewModels fields, then persist it back thru EF.
    }
}

您将拥有一个数据库存储库类,它通过一些干净的方法为您获取这些 EF 实体:

public static class DatabaseRepository
{
    public static List<Capsule> GetAllCapsules()
    {
        // your EF calls/whatever go here.
    }

    public static RawValues GetRawValueObjectById(int pk)
    {
        // your EF calls/whatever go here.
    }
}

不确定您是如何决定传递您关心的“RawValues”实体的 ID,但这里有一对通过 QueryString 来的控制器操作:

public ActionResult RawValues(int pk) 
{
    var rawValuesVM = new ViewModels.RawValuesEditingViewModel();
    try
    {
        rawValuesVM.LoadModelFieldsFromDataObject(pk);
    }
    catch (Exception ex)
    {
        // however you wish to handle a bad lookup
    }
    return View(rawValuesVM);
}

[HttpPost]
public ActionResult RawValues(ViewModels.RawValuesEditingViewModel rawValuesVM, int pk)
{
    if (ModelState.IsValid)
    {
        try
        {
            rawValuesVM.ExecuteRawValuesUpdate(pk);
            // Redirect or something here.
        }
        catch (Exception ex)
        {
            ModelState.AddModelError(string.Empty, ex);
        }
    }
    return View(rawValuesVM);
}

最后,您的 View 将被强绑定到RawValuesEditingViewModel,并且您将显示普通字段,并且对于所选 Capsule 的下拉列表,它将如下所示:

@Html.DropdownListFor(mode => model.SelectedCapsulePk, Model.CapsulesToSelectFrom)
于 2013-03-23T19:57:14.687 回答