C# 绑定包含嵌套对象的ViewModel类

C# 绑定包含嵌套对象的ViewModel类,c#,asp.net-mvc,selectlist,selectlistitem,C#,Asp.net Mvc,Selectlist,Selectlistitem,我创建了一个类,它保存其他复杂类的对象 比如说 class A { public int ID { set; get; } public string MyObjectName {set; get; } public B ObjectOfTypeB { set; get; } } class B { public int ID { set; get; } public int CategoryNumber { set; get; }

我创建了一个类,它保存其他复杂类的对象

比如说

class A {

    public int ID { set; get; }

    public string MyObjectName {set; get; }

    public B ObjectOfTypeB { set; get; }

}

class B {

    public int ID { set; get; }

    public int CategoryNumber { set; get; }

    public string CategoryDescription { set; get; }

}
现在我有了一个控制器方法来创建类型a的对象。我搭建了一个视图来创建我的模型(类a)。但由于A持有复杂类型,它不知道如何为B类型创建输入字段

在我的create函数中

// helper method to get a list of the possible B objects - 
// this method will eventually query a database. for now just static objects

private List<Category> getBobjects()
{
    List<B> bs = new List<B>();
    bs.Add(new B() { ID = 1, CategoryNumber = 2, CategoryDescription = "Config 1" });
    bs.Add(new B() { ID = 2, CategoryNumber = 3, CategoryDescription = "Config 2" });
    return bs;
}

[HttpGet]
public ActionResult Create()
{
    // Adding to the view bags the categories to display
    ViewBag.bs = getBobjects();
    return View();
}
我假设在提交表单时,ObjectOfTypeB中的数据将绑定到类型A的post-back对象,但事实并非如此

有人能解释一下我如何将特定字段的可能值列表传递给视图,并让回发将该值绑定到返回的对象上吗


[Bug Print Screen][1]

您的绑定不正确。如果您试图填充
ObjectOfTypeB
属性的
ID
属性,那么您的
DropDownListFor
应该绑定到
model=>model.ObjectOfTypeB.ID

若您查看源代码,若您希望它在回发时自动填充该属性,那个么您的源代码看起来应该类似于

在这种情况下,我可能会使用ViewModel(VM)来表示您的模型。您并不是真正填写完整的对象B,因为B包含与所选ID相关的类别和描述——换句话说,这三个属性绑定在一起,不能单独填写

我会这样做:

class AViewModel
{
    public int ID {set;get;}

    public string MyObjectName {set; get;}

    public int IDofB { set; get; }
}

为了使您的生活更容易在A和AViewModel之间进行转换,请查看AutoMapper之类的工具。

您必须再次填充
视图包
,才能将绑定返回到
视图
。您可以创建一个填充此ViewBag的方法,并在get/post方法add/edit上使用它。试着只使用基本类型(
string
int
double
bool
)来保持您的
ViewModels
(我喜欢称为
InputModel
),换句话说,将B复杂类型更改为a
int
。试着这样做:

private void SetViewBagCombo(int selectedValue = 0)
{
   ViewBag.bs = new SelectList(getBobjects(), "Id", "CategoryDescription", selectedValue);
}

public ActionResult Create()
{
   SetViewBagCombo(); 
   return View();   
}

[HttpPost]
public ActionResult Create(A input)
{
   if (ModelState.IsValid)
   {
      // persist it
      return RedirectToAction("Index");
   }

   SetViewBagCombo(input.B.Id); 
   return View();   
}
在你看来:

@Html.DropDownListFor(model => model.IdOfB, (SelectList)ViewBag.bs, "Select...")

希望这有帮助,谢谢。

我为这个复杂的类类型模型创建了一个viewmodel

每个嵌套对象都有一个键,这些键使用引用对象类型中的selectlist来显示文本


在这之后,我在回帖中将viewmodel转换回模型的类型。

在回帖之后,您必须获取数据并再次绑定到您的模型。提交后,您将只获得choosen数据的id。我认为Felipes的答案是正确的,但在您的情况下,您必须设置ViewBag.bs=GetBobObjects();在用[HttpPost]属性标记的ActionResult中。我尝试了以下代码。我有一些错误的打印屏幕,如果你能检查出来的话。似乎它仍然没有约束力。(注意类的名称与上面写的不同)这是因为dropdown没有得到除null之外的项值。在getCategories()中,使用IList而不是List,并按照您编写的那样将其余部分保留在函数中。在getDropDownlitItems()函数中写入:IList objlist=getCategories();foreach(对象[]对象列表中的arObject){SelectListItem SelectListItem=new SelectListItem();SelectListItem.Value=arObject[0].ToString();SelectListItem.Text=arObject[1].ToString();ilSelectList.Add(SelectListItem);}并保持您所写的返回类型。
@Html.DropDownListFor(model => model.IdOfB, (SelectList)ViewBag.bs, "Select...")
  private IList getBobjects()
        {
        List<B> bs = new List<B>();
        bs.Add(new B() { ID = 1, CategoryNumber = 2, 
             CategoryDescription = "Config 1" });
        bs.Add(new B() { ID = 2, CategoryNumber = 3, 
             CategoryDescription = "Config 2" });
        return bs;
        }

    public IList<SelectListItem> GetDropdownlistItems()
    {
        IList<SelectListItem> ilSelectList = new List<SelectListItem>();

        IList objlist = getBobjects();
        foreach (object[] arrobject in objlist)
        {
            SelectListItem selectListItem = new SelectListItem();
            selectListItem.Value = arrobject[0].ToString();
            selectListItem.Text = arrobject[1].ToString();
            ilSelectList.Add(selectListItem);
        }

        return ilSelectList;
    }

    public ActionResult Create()
    {
        IList<SelectListItem> ilSelectListItems = GetDropdownlistItems();
        ViewBag.bs = ilSelectListItems;
        return View();
    } 
@Html.DropDownList("bs", new SelectList(ViewBag.bs, "Text", "Value"))