我跟史蒂芬·桑德森的博客 - 的http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
当我尝试添加的项目另一行,而不是增加其发送我行的网址与返回的局部视图。
如何发生,从而增加了实际的行吗?我prevent这种
@model IEnumerable的< MovinMyStuff.Domain.Entities.MoveItem>
@using MovinMyStuff.WebUI.HtmlHelpers
@ {
ViewBag.Title =指数;
}
< H1>我的移动项目< / H1>
@using(Html.BeginForm())
{
<表类=移动项目>
&其中; TR>
<第i个
项目
< /第i个
百分位类=维头>
大号
< /第i个
百分位类=维头>
W¯¯
< /第i个
百分位类=维头>
H
< /第i个
百分位类=重头>
重量
< /第i个
百分位类=数量头>
数量
< /第i个
<第i个
Addt'l工作
< /第i个
< / TR>
&其中; TR>
< TD合并单元格=7>
< DIV ID =editorRows>
@foreach(以模型的VaR项)
{
Html.RenderPartial(_ MoveItemEditorRow,项目);
}
< / DIV>
< / TD>
< / TR>
< /表>
@ Html.ActionLink(添加项目,添加,新{面积=客户},{新的id =的addItem})
<输入类型=提交值=完成/>
}
@model MovinMyStuff.Domain.Entities.MoveItem
@using MovinMyStuff.WebUI.HtmlHelpers
@using(Html.BeginCollectionItem(moveitems))
{
< DIV CLASS =editorRow>
&其中; TR>
< TD类=项目名称>
@ Html.TextBoxFor(型号=> model.MoveItemType)
@ Html.ValidationMessageFor(型号=> model.MoveItemType)
< / TD>
< TD类=项维>
@ Html.EditorFor(型号=> model.Length)
@ Html.ValidationMessageFor(型号=> model.Length)
< / TD>
< TD类=项维>
@ Html.EditorFor(型号=> model.Width)
@ Html.ValidationMessageFor(型号=> model.Width)
< / TD>
< TD类=项维>
@ Html.EditorFor(型号=> model.Height)
@ Html.ValidationMessageFor(型号=> model.Height)
< / TD>
< TD类=项重>
@ Html.EditorFor(型号=> model.Weight)
@ Html.ValidationMessageFor(型号=> model.Weight)
< / TD>
< TD类=项目,数量>
@ Html.EditorFor(型号=> model.Quantity)
@ Html.ValidationMessageFor(型号=> model.Quantity)
< / TD>
< TD类=工作项目组>
<表类=工作项目>
&其中; TR>
< TD>大会< / TD>
< TD>
@ Html.EditorFor(型号=> model.Assemble)
@ Html.ValidationMessageFor(型号=> model.Assemble)
< / TD>
< / TR>
< /表>
<表类=工作项目>
&其中; TR>
< TD>玻璃和LT; / TD>
< TD>
@ Html.EditorFor(型号=> model.HasGlass)
@ Html.ValidationMessageFor(型号=> model.HasGlass)
< / TD>
< / TR>
< /表>
< / TD>
< / TR>
< / DIV>
}
使用系统;
使用System.Collections.Generic;
使用System.Data这;
使用System.Data.Entity的;
使用System.Linq的;
使用的System.Web;
使用System.Web.Mvc;
使用MovinMyStuff.Domain.Entities;
使用MovinMyStuff.Domain.Concrete;
命名空间MovinMyStuff.WebUI.Areas.Client.Controllers
{
公共类MyMoveItemsController:控制器
{
私人EFDbContext DB =新EFDbContext();
//
// GET:/客户/ MyMoveItems /
公众的ActionResult指数()
{
变种moveitems = db.MoveItems.Include(米=> m.Move);
返回查看(moveitems);
}
[HttpPost]
公众的ActionResult指数(IEnumerable的<移动选项> moveitems)
{
返回视图(已完成,moveitems);
}
公共PartialViewResult的Add()
{
返回PartialView(_ MoveItemEditorRow,新移动选项());
}
}
}
使用系统;
使用System.Collections.Generic;
使用的System.Web;
使用System.Web.Mvc;
命名空间MovinMyStuff.WebUI.HtmlHelpers
{
公共静态HTML类prefixScopeExtensions
{
私人常量字符串idsToReuseKey =__html prefixScopeExtensions_IdsToReuse_;
公共静态IDisposable的BeginCollectionItem(这HtmlHelper的HTML,串集合名)
{
VAR idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext,集合名);
字符串的ItemIndex = idsToReuse.Count> 0? 。idsToReuse.Dequeue():Guid.NewGuid()的ToString();
//自动完成=关是需要解决一个非常恼人的Chrome浏览器的行为由此重用旧值用户点击后退,这将导致xyz.index和XYZ后[...]值不同步。
html.ViewContext.Writer.WriteLine(的String.Format(<输入类型= \隐藏\名称= \{0} .index \自动完成= \关\的价值= \{1} \ />中,集合名,html.En code(的ItemIndex)));
返回BeginHtmlField prefixScope(HTML,的String.Format({0} {1}],集合名,的ItemIndex));
}
公共静态IDisposable的BeginHtmlField prefixScope(这HtmlHelper的HTML,串htmlField preFIX)
{
返回新HtmlField prefixScope(html.ViewData.TemplateInfo,htmlField preFIX);
}
私有静态队列<字符串> GetIdsToReuse(HttpContextBase HttpContext的,串集合名)
{
//我们需要使用下面的服务器端验证失败的ID相同的序列,
//否则框架将不会呈现验证错误消息每个项目旁边。
字符串键= idsToReuseKey +集合名;
VAR队列=(队列<字符串>)httpContext.Items [关键];
如果(队列== NULL){
httpContext.Items [关键] =队列=新问答LT;字符串>();
VAR previouslyUsedIds = httpContext.Request [集合名+.index];
如果(!string.IsNullOrEmpty(previouslyUsedIds))
的foreach($ p中$ pviouslyUsedIds.Split字符串previouslyUsedId(,))
queue.Enqueue(previouslyUsedId);
}
返回队列;
}
私有类HtmlField prefixScope:IDisposable的
{
私人只读TemplateInfo templateInfo;
私人只读字符串previousHtmlField preFIX;
公共HtmlField prefixScope(TemplateInfo templateInfo,串htmlField preFIX)
{
this.templateInfo = templateInfo;
previousHtmlField preFIX = templateInfo.HtmlField preFIX;
templateInfo.HtmlField preFIX = htmlField preFIX;
}
公共无效的Dispose()
{
templateInfo.HtmlField preFIX = previousHtmlField preFIX;
}
}
}
}
$(#的addItem)。点击(函数(){
$阿贾克斯({
网址:this.href,
缓存:假的,
成功:函数(HTML){$(#editorRows)追加(HTML)。 }
});
返回false;
});
$(a.deleteRow)。生活(点击,函数(){
$(本)。家长(div.editorRow:第一),删除();
返回false;
});
<!DOCTYPE HTML>
< HTML>
< HEAD>
<元字符集=utf-8/>
<冠军> @ ViewBag.Title< /标题>
<链接HREF =@ Url.Content(〜/内容/ Site.css)相对=样式类型=文本/ CSS/>
<脚本SRC =@ Url.Content(〜/脚本/ jQuery的-1.5.1.js)类型=文/ JavaScript的>< / SCRIPT>
<脚本SRC =@ Url.Content(〜/脚本/ MicrosoftAjax.js)类型=文/ JavaScript的>< / SCRIPT>
<脚本SRC =@ Url.Content(〜/脚本/ Modernizr的-2.5.3.min.js)类型=文/ JavaScript的>< / SCRIPT>
<脚本SRC =@ Url.Content(〜/脚本/ MMS-custom.js)类型=文/ JavaScript的>< / SCRIPT>
@(Html.Telerik()。StyleSheetRegistrar()
.DefaultGroup(组=> group.Add(telerik.common.css)
。新增(telerik.default.css))
)
< /头>
<身体GT;
&其中;节>
@RenderBody()
< /节>
< /身体GT;
< / HTML>
解决方案
试试这个:
第一:确保您的jQuery code(脚本/ MMS-custom.js
)里面 $(的document.ready
- 它看起来并不像它如果是这样,如果你上面张贴整个文件
如果说本身并不解决它,试试这个:
二:
$(#的addItem)。点击(函数(){
$阿贾克斯({
网址:this.href,
缓存:假的,
成功:功能(数据){$(#editorRows)追加(数据)。返回false;}
});
返回false;
});
代替你的code:
$(#的addItem)。点击(函数(){
$阿贾克斯({
网址:this.href,
缓存:假的,
成功:函数(HTML){$(#editorRows)追加(HTML)。 }
});
返回
我使用的博客文章作为参考点时,也有类似的问题。
I followed Steven Sanderson's blog - http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
When I try to add another row of items, rather than adding the row it sends me to the url with the returned partial view.
How do I prevent this from happening and hence add an actual row?
@model IEnumerable<MovinMyStuff.Domain.Entities.MoveItem>
@using MovinMyStuff.WebUI.HtmlHelpers
@{
ViewBag.Title = "Index";
}
<h1>My Move Items</h1>
@using (Html.BeginForm())
{
<table class="move-item">
<tr>
<th>
Item
</th>
<th class="dimension-header">
L
</th>
<th class="dimension-header">
W
</th>
<th class="dimension-header">
H
</th>
<th class="weight-header">
Wt
</th>
<th class="qty-header">
Qty
</th>
<th>
Addt'l Work
</th>
</tr>
<tr>
<td colspan="7">
<div id="editorRows">
@foreach (var item in Model)
{
Html.RenderPartial("_MoveItemEditorRow", item);
}
</div>
</td>
</tr>
</table>
@Html.ActionLink("Add Item", "Add", new { area = "Client" }, new { id = "addItem" })
<input type="submit" value="Finished" />
}
@model MovinMyStuff.Domain.Entities.MoveItem
@using MovinMyStuff.WebUI.HtmlHelpers
@using (Html.BeginCollectionItem("moveitems"))
{
<div class="editorRow">
<tr>
<td class="item-name">
@Html.TextBoxFor(model => model.MoveItemType)
@Html.ValidationMessageFor(model => model.MoveItemType)
</td>
<td class="item-dimension">
@Html.EditorFor(model => model.Length)
@Html.ValidationMessageFor(model => model.Length)
</td>
<td class="item-dimension">
@Html.EditorFor(model => model.Width)
@Html.ValidationMessageFor(model => model.Width)
</td>
<td class="item-dimension">
@Html.EditorFor(model => model.Height)
@Html.ValidationMessageFor(model => model.Height)
</td>
<td class="item-weight">
@Html.EditorFor(model => model.Weight)
@Html.ValidationMessageFor(model => model.Weight)
</td>
<td class="item-qty">
@Html.EditorFor(model => model.Quantity)
@Html.ValidationMessageFor(model => model.Quantity)
</td>
<td class="work-items-group">
<table class="work-items">
<tr>
<td>Assembly</td>
<td>
@Html.EditorFor(model => model.Assemble)
@Html.ValidationMessageFor(model => model.Assemble)
</td>
</tr>
</table>
<table class="work-items">
<tr>
<td>Glass</td>
<td>
@Html.EditorFor(model => model.HasGlass)
@Html.ValidationMessageFor(model => model.HasGlass)
</td>
</tr>
</table>
</td>
</tr>
</div>
}
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MovinMyStuff.Domain.Entities;
using MovinMyStuff.Domain.Concrete;
namespace MovinMyStuff.WebUI.Areas.Client.Controllers
{
public class MyMoveItemsController : Controller
{
private EFDbContext db = new EFDbContext();
//
// GET: /Client/MyMoveItems/
public ActionResult Index()
{
var moveitems = db.MoveItems.Include(m => m.Move);
return View(moveitems);
}
[HttpPost]
public ActionResult Index(IEnumerable<MoveItem> moveitems)
{
return View("Completed", moveitems);
}
public PartialViewResult Add()
{
return PartialView("_MoveItemEditorRow", new MoveItem());
}
}
}
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
namespace MovinMyStuff.WebUI.HtmlHelpers
{
public static class HtmlPrefixScopeExtensions
{
private const string idsToReuseKey = "__htmlPrefixScopeExtensions_IdsToReuse_";
public static IDisposable BeginCollectionItem(this HtmlHelper html, string collectionName)
{
var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext, collectionName);
string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : Guid.NewGuid().ToString();
// autocomplete="off" is needed to work around a very annoying Chrome behaviour whereby it reuses old values after the user clicks "Back", which causes the xyz.index and xyz[...] values to get out of sync.
html.ViewContext.Writer.WriteLine(string.Format("<input type=\"hidden\" name=\"{0}.index\" autocomplete=\"off\" value=\"{1}\" />", collectionName, html.Encode(itemIndex)));
return BeginHtmlFieldPrefixScope(html, string.Format("{0}[{1}]", collectionName, itemIndex));
}
public static IDisposable BeginHtmlFieldPrefixScope(this HtmlHelper html, string htmlFieldPrefix)
{
return new HtmlFieldPrefixScope(html.ViewData.TemplateInfo, htmlFieldPrefix);
}
private static Queue<string> GetIdsToReuse(HttpContextBase httpContext, string collectionName)
{
// We need to use the same sequence of IDs following a server-side validation failure,
// otherwise the framework won't render the validation error messages next to each item.
string key = idsToReuseKey + collectionName;
var queue = (Queue<string>)httpContext.Items[key];
if (queue == null) {
httpContext.Items[key] = queue = new Queue<string>();
var previouslyUsedIds = httpContext.Request[collectionName + ".index"];
if (!string.IsNullOrEmpty(previouslyUsedIds))
foreach (string previouslyUsedId in previouslyUsedIds.Split(','))
queue.Enqueue(previouslyUsedId);
}
return queue;
}
private class HtmlFieldPrefixScope : IDisposable
{
private readonly TemplateInfo templateInfo;
private readonly string previousHtmlFieldPrefix;
public HtmlFieldPrefixScope(TemplateInfo templateInfo, string htmlFieldPrefix)
{
this.templateInfo = templateInfo;
previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix;
templateInfo.HtmlFieldPrefix = htmlFieldPrefix;
}
public void Dispose()
{
templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix;
}
}
}
}
$("#addItem").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) { $("#editorRows").append(html); }
});
return false;
});
$("a.deleteRow").live("click", function () {
$(this).parents("div.editorRow:first").remove();
return false;
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.5.1.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/MicrosoftAjax.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/modernizr-2.5.3.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/mms-custom.js")" type="text/javascript"></script>
@(Html.Telerik().StyleSheetRegistrar()
.DefaultGroup(group => group.Add("telerik.common.css")
.Add("telerik.default.css"))
)
</head>
<body>
<section>
@RenderBody()
</section>
</body>
</html>
解决方案
Try this:
First: Make sure your jQuery code (Scripts/mms-custom.js
) is inside $(document.ready
-- it does not look like it is if that is if you posted your entire file above.
If that doesn't fix it by itself, try this:
Second:
$("#addItem").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (data) { $("#editorRows").append(data); return false;}
});
return false;
});
in place of your code:
$("#addItem").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) { $("#editorRows").append(html); }
});
return
I had a similar problem when using that blog post as a point of reference.