问题描述
我有一个视图模型对象,其中包含另一个模型对象类型的List
.当用户在页面上进行查询时,如果返回的List
包含300条以上的记录,我们希望使用分页来减少加载时间(某些搜索结果可以返回14000条以上的记录).我们正在使用的此页面插件.
I have a view model object that contains a List
of another model object type. When the user does a query on the page, if the List
returned contains more than 300 records we want to use paging to keep the loading time down (some search results can return more than 14k records). The paging plugin we're using can be found here.
一旦结果显示在页面上,用户便可以单击特定结果旁边的复选框,在输入文本框中键入一些信息,单击提交",并使用该信息编辑所选记录从文本框中输入.
Once the results have been displayed on the page, the user has the ability to click a check box next to specific results, type in some information in an input text box, hit submit, and have the selected records edited with the information from the text box.
由于我们需要使用IPagedList<>
来启用分页,但是,当您单击提交"时(甚至在该页面还没有命中控制器之前),我们都会收到以下错误消息:
Since we needed to use an IPagedList<>
in order to enable paging, however, when you hit submit (and before the page even hits the controller) we get the following error:
Cannot create an instance of an interface.
查看模型
这是我们用于分页的两个列表对象. zipCodeTerritory
对象保存查询的结果. pagedTerritoryList
用于仅在用户所在的特定页面上显示结果.
These are the two list objects that we use for paging. The zipCodeTerritory
object holds the results of the query. The pagedTerritoryList
is used to display only the results on the specific page the user is on.
//Paging List objects
public IPagedList<ZipCodeTerritory> pagedTerritoryList { get; set; }
public List<ZipCodeTerritory> zipCodeTerritory { get; set; }
public IPagedList PagingMetaData { get; set; }
控制器
这是我们的基本搜索. .ToPagedList
方法用于指定我们要显示的结果范围,并将它们放置在对象中.
This is our basic search. The .ToPagedList
method is used to specify what range of results we want to display and place them in the pagedTerritoryList
object.
//set Paged List counter variables
int pageNumber = page ?? 1;
int pageSize = 300;
//Determine if Territory present?
if (string.IsNullOrWhiteSpace(search.searchTerritory))
{
//State Code ONLY search
search.zipCodeTerritory = (from z in db.ZipCodeTerritory
where z.StateCode.Equals(search.searchState)
select z).ToList();
}
else if(string.IsNullOrWhiteSpace(search.searchState))
{
//Territory ONLY search
search.zipCodeTerritory = (from z in db.ZipCodeTerritory
where z.IndDistrnId.Equals(search.searchTerritory)
select z).ToList();
}
else
{
//Territory AND state search
search.zipCodeTerritory = (from z in db.ZipCodeTerritory
where z.IndDistrnId.Equals(search.searchTerritory) &&
z.StateCode.Equals(search.searchState)
select z).ToList();
}
//Convert list to IPagedList for pagining on Index
search.pagedTerritoryList = search.zipCodeTerritory.ToPagedList(pageNumber, pageSize);
//Set Paged List objects
search.PagingMetaData = new StaticPagedList<ZipCodeTerritory>(search.zipCodeTerritory, pageNumber, pageSize,
search.zipCodeTerritory.Count).GetMetaData();
return View(search);
查看
这是显示搜索结果的表格.如果用户选中该复选框,然后单击clone
或delete
按钮,则应该将结果发布回控制器的Update
方法,并执行适当的编辑或删除操作.用户想要在编辑中覆盖的信息以格式(在table
上方)输入到newTerritory/Description/etc
字段中.
This is the form that displays the search results. If a user checks the check box, then hits either clone
or delete
buttons, the results are supposed to be posted back to the controller's Update
method and appropriate edits or deletes performed. The information the user wants to overlay in an edit are input into the newTerritory/Description/etc
fields in the form (above the table
).
关于@Html.PagedListPager
,我发现我必须将相同的搜索标准从页面传递回索引方法,因此RouteValueDictionary
中的参数过多.
Regarding the @Html.PagedListPager
I found I had to pass back to the index method the same search criteria from the page, thus the excessive amount of parameters in the RouteValueDictionary
.
@if (Model.zipCodeTerritory.Count > 0)
{
using (Html.BeginForm("Update", "ZipCodeTerritory", FormMethod.Post))
{
@Html.HiddenFor(model => model.searchZip)
@Html.HiddenFor(model => model.searchDate)
@Html.HiddenFor(model => model.searchState)
<div id="cloneBox">
<div id="rw1">
@Html.LabelFor(model => model.newTerritory)
@Html.TextBoxFor(model => model.newTerritory, new { style = "width: 30px;padding-left:10px;", maxLength = 3 })
@Html.LabelFor(model => model.newDescription)
@Html.TextBoxFor(model => model.newDescription, new { style = "width: 250px;padding-left:10px;", maxLength = 30 })
@Html.LabelFor(model => model.newEffectiveDate)
@Html.TextBoxFor(model => model.newEffectiveDate, new { style = "width: 80px;padding-left:10px;" })
<div id="rw2" style="padding-top: 10px;">
@Html.LabelFor(model => model.newChannelCode)
@Html.DropDownListFor(model => model.newChannelCode, Model.ChannelCodes, " ")
@Html.LabelFor(model => model.newStateCode)
@Html.DropDownListFor(model => model.newStateCode, Model.StateCodes, " ")
</div>
</div>
</div>
<br/>
<div id="buttonDiv">
<button type="submit" id="CloneButton" name="button" value="clone">Apply New Data</button>
<button type="submit" id="deleteButton" name="button" value="delete">Delete Selected Items</button>
</div>
@*Display paging only if necessary*@
if (Model.pagedTerritoryList.Count >= 300)
{
<div id="pagingDiv">
@Html.PagedListPager(new StaticPagedList<Monet.Models.ZipCodeTerritory>(Model.zipCodeTerritory, Model.PagingMetaData) ,
Page => Url.Action("Index", new RouteValueDictionary()
{
{ "Page", Page},
{ "searchZip", Model.searchZip },
{ "searchActiveOnly", Model.searchActiveOnly },
{ "searchDate", Model.searchDate },
{ "searchState", Model.searchState },
{ "searchTerritory", Model.searchTerritory },
{ "searchChannel" , Model.searchChannelCode }
}), PagedListRenderOptions.DefaultPlusFirstAndLast)
</div>
}
<table id="thetable" class="tablesorter" >
<thead>
<th>@Html.CheckBox("SelectAll")</th>
<th>State</th>
<th>Territory</th>
<th>Zip</th>
<th>Description</th>
<th>Effective</th>
<th>End Date</th>
<th>Last Update Date</th>
<th>Channel</th>
<th></th>
</thead>
<tbody id="tableBody">
@for (int i = 0; i < Model.pagedTerritoryList.Count; i++)
{
<tr id="@(Model.lastEditedId == Model.pagedTerritoryList[i].Id ? "lastEdit" : "")">
<td>
@Html.CheckBoxFor(model => model.pagedTerritoryList[i].Update)
@Html.HiddenFor(model => model.pagedTerritoryList[i].Update)
</td>
<td>
@Html.DisplayFor(model => model.pagedTerritoryList[i].StateCode)
@Html.HiddenFor(model => model.pagedTerritoryList[i].StateCode)
</td>
<td>
@Html.DisplayFor(model => model.pagedTerritoryList[i].IndDistrnId)
@Html.HiddenFor(model => model.pagedTerritoryList[i].IndDistrnId)
</td>
<td>
@Html.DisplayFor(model => model.pagedTerritoryList[i].ZipCode)
@Html.HiddenFor(model => model.zipCodeTerritory[i].ZipCode)
</td>
<td>
@Html.DisplayFor(model => model.pagedTerritoryList[i].DrmTerrDesc)
@Html.HiddenFor(model => model.pagedTerritoryList[i].DrmTerrDesc)
</td>
<td>
@Html.DisplayFor(model => model.pagedTerritoryList[i].EffectiveDate)
@Html.HiddenFor(model => model.pagedTerritoryList[i].EffectiveDate)
</td>
<td>
@if (Model.pagedTerritoryList[i].EndDate.Date != DateTime.MaxValue.Date)
{
@Html.DisplayFor(model => model.pagedTerritoryList[i].EndDate)
@Html.HiddenFor(model => model.pagedTerritoryList[i].EndDate)
}
</td>
<td>
@Html.DisplayFor(model => model.pagedTerritoryList[i].LastUpdateDate)
@Html.HiddenFor(model => model.pagedTerritoryList[i].LastUpdateDate)
</td>
<td>
@Html.DisplayFor(model => model.pagedTerritoryList[i].ChannelCode)
@Html.HiddenFor(model => model.pagedTerritoryList[i].ChannelCode)
</td>
@if (ViewBag.SecurityLevel >= 4)
{
<td>
@Html.ActionLink("Edit", "Edit", new
{
id = Model.zipCodeTerritory[i].Id,
searchZip = Model.searchZip,
searchActiveOnly = Model.searchActiveOnly,
searchDate = Model.searchDate,
searchState = Model.searchState,
searchTerritory = Model.searchTerritory,
searchChannelCode = Model.searchChannelCode
})
@Html.HiddenFor(model => model.zipCodeTerritory[i].Id)
</td>
}
</tr>
}
</tbody>
</table>
}
}
编辑
根据下面的评论,这是表单发布到的方法的签名.它包含ZipCodeIndex
的一个实例,该实例最初会加载到页面上,再加上button
的文本来确定我们要执行的是clone
还是delete
Per the comment below, here is the signature for the method the form is posting to. It contains an instance of the ZipCodeIndex
that gets loaded on the page originally, plus the text from the button
to determine whether we're doing a clone
or delete
[HttpPost]
public ActionResult Update(ZipCodeIndex updateZip, string button)
{
第二次修改
尝试了此问题中的方法,但仍收到原始错误消息(无法创建以下内容的实例接口").
Tried the method from this question but still receiving the original error message ("cannot create instance of an interface").
推荐答案
我能够完全摆脱困境,但是我认为这不是最好的解决方案.如果有人可以提供更好的答案,将不胜感激,但是与此同时,我将在此处发布.
I was able to completely hack my way out of this, however I don't think it's the best solution. Would love it if someone could provide a better answer however I'll post this up here in the meantime.
由于构建了IPagedList
对象以容纳特定范围的List<>
,所以我刚刚在视图模型上创建了display属性,并在视图上使用了该属性.此列表(而不是IPagedList
)被发布回控制器以进行更新,因此不会发生界面怪异.
Since the IPagedList
object was built to hold a specific range of the List<>
I just made a display property on my view model and used this on my view. This list, not the IPagedList
gets posted back to the controller for the updates, so no interface weirdness occurs.
查看模型
//Paging List objects
public IPagedList<ZipCodeTerritory> pagedTerritoryList { get; set; }
public List<ZipCodeTerritory> zipCodeTerritory { get; set; }
public List<ZipCodeTerritory> displayForPaging { get; set; }
控制器
//Convert list to IPagedList for pagining on Index
search.pagedTerritoryList = search.zipCodeTerritory.ToPagedList(pageNumber, pageSize);
search.displayForPaging = search.pagedTerritoryList.ToList();
查看
<td>
@Html.CheckBoxFor(model => model.displayForPaging[i].Update)
@Html.HiddenFor(model => model.displayForPaging[i].Update)
</td>
<td>
.
.
这篇关于无法创建接口的实例(PagedList)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!