Reputation: 15286
I've created a class which holds objects of other complex classes.
So for instance
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; }
}
Now I have a controller method which creates objects of type A. I scaffolded a view for creation of my model (class A). But because A holds a complex type it doesn't know how to create the input fields for the B type.
In my create function
// 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();
}
And in the View
@Html.DropDownListFor(model => model.ObjectOfTypeB,
new SelectList(ViewBag.bs, "ID", "CategoryDescription"))
I assumed that when submit the form, the data from the ObjectOfTypeB would be binded to the post back object of type A. But this isn't happening.
Can anybody explain how I can pass a list of possible values for a particular field to the view and have the postback bind the value onto the returned object?
[Bug Print Screen][1]
Upvotes: 2
Views: 1519
Reputation: 15286
I created a viewmodel for that complex class type model
had a key for each of the nested objects and for those keys used a selectlist from the referenced object type for the text to display.
After that on the post back I translated the viewmodel back to the type of the model
Upvotes: 0
Reputation: 3584
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();
}
and in view:
@Html.DropDownList("bs", new SelectList(ViewBag.bs, "Text", "Value"))
Hope this helps, thanks.
Upvotes: 0
Reputation: 38618
You have to fill the ViewBag
again to return the bind to your View
. You could create a method that fill this ViewBag for you and use it on the get/post methods add/edit as well. Try to keep your ViewModels
(I like to call as InputModel
) only with primitive types (string
, int
, double
, bool
) in other words, change the B complex type to a int
. Try something like this:
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();
}
And in your View:
@Html.DropDownListFor(model => model.IdOfB, (SelectList)ViewBag.bs, "Select...")
Upvotes: 0
Reputation: 9763
Your binding is not correct. If you're trying to fill the ID
property of your ObjectOfTypeB
property, then your DropDownListFor
should bind to model => model.ObjectOfTypeB.ID
If you view source, your source should look something like <select name="ObjectOfTypeB.ID">
if you expect it to auto-fill that property on postback.
In this case I'd probably use a ViewModel (VM) to represetn your model. You're not REALLY filling out a full object B, as a B contains a category and description related to the ID selected -- in other words, the three properties are bound together and not separately fillable.
I'd do something like:
class AViewModel
{
public int ID {set;get;}
public string MyObjectName {set; get;}
public int IDofB { set; get; }
}
To make your life easier of translating between A and AViewModel, look at tools like AutoMapper.
Upvotes: 1