开发者

How can I bind a list of lists to a view

开发者 https://www.devze.com 2023-03-12 04:58 出处:网络
I have a ViewModel that have a list object containing other list ob开发者_StackOverflowjects and want to bind that to a view.

I have a ViewModel that have a list object containing other list ob开发者_StackOverflowjects and want to bind that to a view.

What I have done so far is to loop through the first list like so:

    for (int i = 0; i < Model.ThFirstList.Count(); i++ )
    {
        Html.EditorFor(model => model.TheFirstList[i] , "myView")
    }

And in "myView" a loop through the other list like so:

    for (int i = 0; i < Model.TheSecondList.Count(); i++ )
    {
        %><%: Html.DropDownListFor(m => m.TheSecondList[i].ThePropertyIWantToSet, aList)%><%
    }

Everything looks fine and on the client side (I think) and the name of the select-fields is like this:

TheFirstList[0].TheSecondList[0].ThePropertyIWantToSet

When I don't choose anything from any of the select boxes and post back the data then TheFirsList and TheSecendList objects is set. However if I choose a value in the list I get Error Code 500 back from the server. My guess is that it can't find any matching Controller method for the request? Because of this I can't set the ThePropertyIWantToSet property.

Can anyone help me on this?

Thanks!


Instead of bothering with foreach loops etc, I would simply use a view model and editor templates. It makes life easier.

So start with a view model:

public class MyViewModel
{
    public IEnumerable<Type1> TheFirstList { get; set; }
}

public class Type1
{
    public IEnumerable<Type2> TheSecondList { get; set; }
}

public class Type2
{
    public string ThePropertyIWantToSet { get; set; }

    public IEnumerable<SelectListItem> Items
    {
        get
        {
            return new[]
            {
                new SelectListItem { Value = "1", Text = "item 1" },
                new SelectListItem { Value = "2", Text = "item 2" },
                new SelectListItem { Value = "3", Text = "item 3" },
            };
        }
    }
}

then a controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        // filling with dummy values => those should probably
        // come from your data store
        var model = new MyViewModel
        {
            TheFirstList = Enumerable.Range(1, 2).Select(x => new Type1
            {
                TheSecondList = Enumerable.Range(1, 3).Select(y => new Type2())
            })
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

Then corresponding ~/Views/Home/Index.cshtml view:

@model MyViewModel
@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.TheFirstList)
    <input type="submit" value="OK" />
}

The ~/Views/Home/EditorTemplates/Type1.cshtml template:

@model Type1
@Html.EditorFor(x => x.TheSecondList)

and finally the ~/Views/Home/EditorTemplates/Type2.cshtml template:

@model Type2
@Html.DropDownListFor(
    x => x.ThePropertyIWantToSet, 
    new SelectList(Model.Items, "Value", "Text")
)

Now in the POST action you will get a nice and properly bound view model. Editor templates will take care of generating the correct input field names. See how easy and clean the code is. No need of writing any loops in the views, worrying about proper indexes, ... just leave this to the framework.


Seeing your view model may be more helpful, but typically when rendering select lists from a view model I use two separate properties: one to store the selected value and the other to actually hold the list itself.

ViewModels with SelectList Design Decison

0

精彩评论

暂无评论...
验证码 换一张
取 消