MVC3 Model binding pagedlist to ViewModel with cus

2019-04-11 14:13发布

问题:

Im trying to produce a paged table of results which is contained in a Partial view. It is dynamically refreshed with ajax calls.

Im reproducing this on a number of pages where it works perfectly, however on a particular page i require the values of the table rows to be bound and returned with the ViewModel.

To achieve this i have tried to use an EditorTemplate for the custom object im using for the PagedList collection. The problem lies where the editortemplate which appears on the PartialView doesnt name correctly for the PagedList collection on the main ViewModel.

Its probably easier if i explain with code.

The main view appears thusly:

@model RequestCreateViewModel
<Code>

<div id="gridContainer">
    @Html.Partial("_PagedCreateRequest")
    @Html.HiddenFor(x => x.PageSize)
    @Html.HiddenFor(x => x.PageNumber)
</div>
<div id="loadingContainer">
</div> 

<More code>

The Partial is thus:

@model IPagedList<CreateRequestModel>
<Code>

<table class="tablesorter"  style="width:750px;">
                <thead>
                    <tr>
</tr>
                </thead>
                <tbody>
                    @Html.EditorFor(x => Model)
                </tbody>
            </table>
        </div>

<div style="float:left">
            @Ajax.ImageActionLink(
                "../../Content/images/first.gif",
                "alt text",
                "PageResults",
                new
                {
                    Page = 1,
                    area = "Admin",
                    SortBy = Model.SortBy,
                    SortDescending = Model.SortDescending,
                    PageSize = Model.PageSize
                },
                new
                {
                    style = "margin-top: 2px;"
                },
                new
                {
                    @readonly = "readonly"
                },
                new AjaxOptions
                {
                    UpdateTargetId = "gridContainer"
                }

                    )
        </div>

+ other pager Ajax pager icons and stuff

The EditorTemplate is:

@model CreateRequestModel

<tr>
    <td>
        @Html.CheckBoxFor(x => x.IsSelected)
    </td>
    <td>
        @Html.DisplayFor(x => x.CompanyName)
        @Html.HiddenFor(x => x.CompanyName)
    </td>
    <td>
        @Html.DisplayFor(x => x.CompanyISIN)
        @Html.HiddenFor(x => x.CompanyISIN)
    </td>
    <td>
        @Html.DisplayFor(x => x.ShareDesc)
        @Html.HiddenFor(x => x.ShareDesc)
    </td>
    <td>
        @Html.DisplayFor(x => x.ShareClass)
        @Html.HiddenFor(x => x.ShareClass)
    </td>
</tr>

The ViewModel is:

public class RequestCreateViewModel : ViewModelBase
{
    public IPagedList<CreateRequestModel> PagedList { get; set; }

The CreateRequestModel is:

public class CreateRequestModel
{
    public int RequestId { get; set; }

    public bool IsSelected { get; set; }

    public string CompanyName { get; set; }
    public string CompanyISIN { get; set; }
    public string ShareDesc { get; set; }
    public string ShareClass { get; set; }
}

But when posted back to the controller (code):

 [Authorize(Roles = "Foo")]
 [HttpPost]
 public ActionResult RequestCreate(RequestCreateViewModel model)

The property IPagedList is not bound to the ViewModel (obviously) because the naming standards of the EditorTemplate are

eg: [0].Whatever

rather than:

PagedList[0].Whatever

I cant instantiate a bound copy of the interface for an IPagedList in the ViewModel either. So how do i go about getting the information off the main View back to the model?

I'm thinking a custom Model Binder might be the solution, but my experience is minimal in this area. The end purpose of this is to determine the value of the checkboxes on the table. The user will select or not and i need to know what theyve selected!

Many thanks for any help.

回答1:

Have a look at this post: http://weblogs.asp.net/nmarun/archive/2010/03/13/asp-net-mvc-2-model-binding-for-a-collection.aspx

The secret is to generate the Name on the control as the collection name with an indexer as

<input id="Products_0__ID" name="Products[0].ID" type="text" value="1" />